]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux IEEE-1394 Updates
authorBen Collins <bcollins@debian.org>
Sat, 12 Oct 2002 10:21:27 +0000 (03:21 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 12 Oct 2002 10:21:27 +0000 (03:21 -0700)
 - Cleanup (purge) some of our old compat code (never thouched)
 - Fix dv1394 compilation warnings without devfs
 - Added new config-rom handling features. Allows for on-the-fly
   config-rom generation for dynamic functionality of the host nodes.
 - Convert to workqueue from taskqueue interfaces. This is actually
   abstracted compatibility code between tqueue/workqueue.

22 files changed:
drivers/ieee1394/cmp.c
drivers/ieee1394/csr.c
drivers/ieee1394/csr.h
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/eth1394.h
drivers/ieee1394/highlevel.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_transactions.h
drivers/ieee1394/ieee1394_types.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/pcilynx.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/raw1394.h
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c

index f2ef4a2d11ff124ec10c43fcbb89b42115dad213..08d2e515434503d5cb1c722c297462dd988075f0 100644 (file)
@@ -199,7 +199,7 @@ static void cmp_remove_host(struct hpsb_host *host)
 }
 
 static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                   u64 addr, unsigned int length)
+                   u64 addr, unsigned int length, u16 flags)
 {
        int csraddr = addr - CSR_REGISTER_BASE;
        int plug;
@@ -235,7 +235,7 @@ static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
 }
 
 static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int extcode)
+                   u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags)
 {
        int csraddr = addr - CSR_REGISTER_BASE;
        int plug;
index 63e6829e51b085f08928d7574948af6fa254a034..7194c396d98efab7ae8838721dcf23ca73d65a4c 100644 (file)
@@ -4,20 +4,33 @@
  * CSR implementation, iso/bus manager implementation.
  *
  * Copyright (C) 1999 Andreas E. Bombe
+ *               2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
  *
  * This code is licensed under the GPL.  See the file COPYING in the root
  * directory of the kernel sources for details.
+ *
+ *
+ * Contributions:
+ *
+ * Manfred Weihs <weihs@ict.tuwien.ac.at>
+ *        configuration ROM manipulation
+ *
  */
 
 #include <linux/string.h>
+#include <linux/module.h> /* needed for MODULE_PARM */
 
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394.h"
 #include "highlevel.h"
 
+/* Module Parameters */
+/* this module parameter can be used to disable mapping of the FCP registers */
+MODULE_PARM(fcp,"i");
+MODULE_PARM_DESC(fcp, "FCP-registers");
+static int fcp = 1;
 
-/* FIXME: this one won't work on little endian with big endian data */
 static u16 csr_crc16(unsigned *data, int length)
 {
         int check=0, i;
@@ -25,7 +38,7 @@ static u16 csr_crc16(unsigned *data, int length)
 
         for (i = length; i; i--) {
                 for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
-                        sum = ((next >> 12) ^ (*data >> shift)) & 0xf;
+                        sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;
                         next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
                 }
                 check = next & 0xffff;
@@ -60,6 +73,8 @@ static void host_reset(struct hpsb_host *host)
                             | csr_crc16(host->csr.topology_map + 1,
                                         host->selfid_count + 2));
 
+        host->csr.speed_map[1] = 
+                cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);
         host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16 
                                              | csr_crc16(host->csr.speed_map+1,
                                                          0x3f1));
@@ -71,7 +86,7 @@ static void add_host(struct hpsb_host *host)
         host->csr.lock = SPIN_LOCK_UNLOCKED;
 
         host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
-
+        host->csr.rom_version           = 0;
         host->csr.state                 = 0;
         host->csr.node_ids              = 0;
         host->csr.split_timeout_hi      = 0;
@@ -84,13 +99,52 @@ static void add_host(struct hpsb_host *host)
         host->csr.channels_available_lo = ~0;
 }
 
+int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, 
+       size_t size, unsigned char rom_version)
+{
+        int ret,flags;
+        spin_lock_irqsave(&host->csr.lock, flags); 
+        if (rom_version != host->csr.rom_version)
+                 ret = -1;
+        else if (size > (CSR_CONFIG_ROM_SIZE << 2))
+                 ret = -2;
+        else {
+                 memcpy(host->csr.rom,new_rom,size);
+                 host->csr.rom_size=size;
+                 host->csr.rom_version++;
+                 ret=0;
+        }
+        spin_unlock_irqrestore(&host->csr.lock, flags);
+        return ret;
+}
+
+int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, 
+       size_t buffersize, size_t *rom_size, unsigned char *rom_version)
+{
+        int ret,flags;
+        spin_lock_irqsave(&host->csr.lock, flags); 
+        *rom_version=host->csr.rom_version;
+        *rom_size=host->csr.rom_size;
+        if (buffersize < host->csr.rom_size)
+                 ret = -1;
+        else {
+                 memcpy(buffer,host->csr.rom,host->csr.rom_size);
+                 ret=0;
+        }
+        spin_unlock_irqrestore(&host->csr.lock, flags);
+        return ret;
+}
+
 
 /* Read topology / speed maps and configuration ROM */
 static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                     u64 addr, unsigned int length)
+                     u64 addr, unsigned int length, u16 fl)
 {
         int csraddr = addr - CSR_REGISTER_BASE;
         const char *src;
+        int flags;
+
+        spin_lock_irqsave(&host->csr.lock, flags); 
 
         if (csraddr < CSR_TOPOLOGY_MAP) {
                 if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
@@ -105,6 +159,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
         }
 
         memcpy(buffer, src, length);
+        spin_unlock_irqrestore(&host->csr.lock, flags);
         return RCODE_COMPLETE;
 }
 
@@ -112,7 +167,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
 #define out if (--length == 0) break
 
 static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                     u64 addr, unsigned int length)
+                     u64 addr, unsigned int length, u16 flags)
 {
         int csraddr = addr - CSR_REGISTER_BASE;
         int oldcycle;
@@ -222,7 +277,7 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
 }
 
 static int write_regs(struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, unsigned int length)
+                     quadlet_t *data, u64 addr, unsigned int length, u16 flags)
 {
         int csraddr = addr - CSR_REGISTER_BASE;
         
@@ -302,7 +357,7 @@ static int write_regs(struct hpsb_host *host, int nodeid, int destid,
 
 
 static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                     u64 addr, quadlet_t data, quadlet_t arg, int extcode)
+                     u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl)
 {
         int csraddr = addr - CSR_REGISTER_BASE;
         unsigned long flags;
@@ -379,7 +434,7 @@ static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
 }
 
 static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
-                    quadlet_t *data, u64 addr, unsigned int length)
+                    quadlet_t *data, u64 addr, unsigned int length, u16 flags)
 {
         int csraddr = addr - CSR_REGISTER_BASE;
 
@@ -436,9 +491,11 @@ void init_csr(void)
         hpsb_register_addrspace(hl, &map_ops, 
                                 CSR_REGISTER_BASE + CSR_CONFIG_ROM,
                                 CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
-        hpsb_register_addrspace(hl, &fcp_ops,
+        if (fcp) {
+               hpsb_register_addrspace(hl, &fcp_ops,
                                 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
                                 CSR_REGISTER_BASE + CSR_FCP_END);
+       }
         hpsb_register_addrspace(hl, &map_ops,
                                 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
                                 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
index 3b2ea80bacfa977a5267b072767caeaad434c2c1..ad93097902a589ef831fd49843b76efd59ecbf93 100644 (file)
@@ -41,8 +41,10 @@ struct csr_control {
         quadlet_t bandwidth_available;
         quadlet_t channels_available_hi, channels_available_lo;
 
-        const quadlet_t *rom;
+        quadlet_t *rom;
         size_t rom_size;
+        unsigned char rom_version;
+
 
         quadlet_t topology_map[256];
         quadlet_t speed_map[1024];
index c81ed10d52d7cfb105be6400f2d517d6a594b197..9aba8885c0e02eb5bdd34de43a01c53d6e8ff618 100644 (file)
@@ -97,7 +97,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
 #include <linux/delay.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -2587,6 +2586,7 @@ found:
        return p;
 }
 
+#ifdef CONFIG_DEVFS_FS
 static int dv1394_devfs_add_entry(struct video_card *video)
 {
        char buf[32];
@@ -2694,6 +2694,7 @@ void dv1394_devfs_del( char *name)
                kfree(p);
        }
 }
+#endif /* CONFIG_DEVFS_FS */
 
 /*** IEEE1394 HPSB CALLBACKS ***********************************************/
 
@@ -2852,7 +2853,6 @@ static void dv1394_add_host (struct hpsb_host *host)
 {
        struct ti_ohci *ohci;
        char buf[16];
-       struct dv1394_devfs_entry *devfs_entry;
 
        /* We only work with the OHCI-1394 driver */
        if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
@@ -2874,13 +2874,15 @@ static void dv1394_add_host (struct hpsb_host *host)
 #endif
 
 #ifdef CONFIG_DEVFS_FS
-       devfs_entry = dv1394_devfs_find("dv");
+{
+       struct dv1394_devfs_entry = devfs_entry = dv1394_devfs_find("dv");
        if (devfs_entry != NULL) {
                snprintf(buf, sizeof(buf), "host%d", ohci->id);
                dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry);
                dv1394_devfs_add_dir("NTSC", devfs_entry, NULL);
                dv1394_devfs_add_dir("PAL", devfs_entry, NULL);
        }
+}
 #endif
        
        dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
index fc0118cab4f71887abb1dffd14ceaad9597d49ff..395d3f74d1c0f50b343b6cf689d9e6927af3c1b8 100644 (file)
@@ -77,7 +77,7 @@
        printk(KERN_ERR fmt, ## args)
 
 static char version[] __devinitdata =
-       "$Rev: 546 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 601 $ Ben Collins <bcollins@debian.org>";
 
 /* Our ieee1394 highlevel driver */
 #define ETHER1394_DRIVER_NAME "ether1394"
@@ -522,7 +522,7 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
  * ethernet header, and fill it with some of our other fields. This is
  * an incoming packet from the 1394 bus.  */
 static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
-                           quadlet_t *data, u64 addr, unsigned int len)
+                           quadlet_t *data, u64 addr, unsigned int len, u16 fl)
 {
        struct sk_buff *skb;
        char *buf = (char *)data;
@@ -682,8 +682,8 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
        ptask->skb = skb;
        ptask->addr = addr;
        ptask->dest_node = dest_node;
-       INIT_TQUEUE(&ptask->tq, hpsb_write_sched, ptask);
-       schedule_task(&ptask->tq);
+       HPSB_INIT_WORK(&ptask->tq, hpsb_write_sched, ptask);
+       hpsb_schedule_work(&ptask->tq);
 
        return 0;
 fail:
index 93ff59cb357c9817e8c905487084770405af2673..44c1637182c6a17afb18e8c7325f0459c72f6500 100644 (file)
@@ -56,7 +56,7 @@ struct packet_task {
        struct sk_buff *skb;    /* Socket buffer we are sending */
        nodeid_t dest_node;     /* Destination of the packet */
        u64 addr;               /* Address */
-       struct tq_struct tq;    /* The task */
+       struct hpsb_queue_struct tq;    /* The task */
 };
 
 /* IP1394 headers */
index ebfcd0668658dd3db90e8155d45415648b585d26..bffc57fca7e40d5b5d4c1295eec349690dede6f7 100644 (file)
@@ -5,6 +5,16 @@
  *
  * This code is licensed under the GPL.  See the file COPYING in the root
  * directory of the kernel sources for details.
+ *
+ *
+ * Contributions:
+ *
+ * Christian Toegel <christian.toegel@gmx.at>
+ *        unregister address space
+ *
+ * Manfred Weihs <weihs@ict.tuwien.ac.at>
+ *        unregister address space
+ *
  */
 
 #include <linux/config.h>
@@ -129,6 +139,32 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
         return retval;
 }
 
+int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
+{
+        int retval = 0;
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+
+        write_lock_irq(&addr_space_lock);
+
+        entry = hl->addr_list.next;
+
+        while (entry != &hl->addr_list) {
+                as = list_entry(entry, struct hpsb_address_serve, addr_list);
+                entry = entry->next;
+                if (as->start == start) {
+                        list_del(&as->as_list);
+                        list_del(&as->addr_list);
+                        kfree(as);
+                        retval = 1;
+                        break;
+                }
+        }
+
+        write_unlock_irq(&addr_space_lock);
+
+        return retval;
+}
 
 void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
                          unsigned int channel)
@@ -243,7 +279,7 @@ void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 }
 
 int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                   u64 addr, unsigned int length)
+                   u64 addr, unsigned int length, u16 flags)
 {
         struct hpsb_address_serve *as;
         struct list_head *entry;
@@ -261,7 +297,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
 
                         if (as->op->read != NULL) {
                                 rcode = as->op->read(host, nodeid, buffer,
-                                                    addr, partlength);
+                                                    addr, partlength, flags);
                         } else {
                                 rcode = RCODE_TYPE_ERROR;
                         }
@@ -288,7 +324,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
 }
 
 int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
-                   quadlet_t *data, u64 addr, unsigned int length)
+                   quadlet_t *data, u64 addr, unsigned int length, u16 flags)
 {
         struct hpsb_address_serve *as;
         struct list_head *entry;
@@ -306,7 +342,7 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
 
                         if (as->op->write != NULL) {
                                 rcode = as->op->write(host, nodeid, destid,
-                                                     data, addr, partlength);
+                                                     data, addr, partlength, flags);
                         } else {
                                 rcode = RCODE_TYPE_ERROR;
                         }
@@ -334,7 +370,7 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
 
 
 int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode)
+                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
 {
         struct hpsb_address_serve *as;
         struct list_head *entry;
@@ -349,7 +385,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
                 if (as->end > addr) {
                         if (as->op->lock != NULL) {
                                 rcode = as->op->lock(host, nodeid, store, addr,
-                                                     data, arg, ext_tcode);
+                                                     data, arg, ext_tcode, flags);
                         } else {
                                 rcode = RCODE_TYPE_ERROR;
                         }
@@ -367,7 +403,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
 }
 
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode)
+                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
 {
         struct hpsb_address_serve *as;
         struct list_head *entry;
@@ -383,7 +419,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
                         if (as->op->lock64 != NULL) {
                                 rcode = as->op->lock64(host, nodeid, store,
                                                        addr, data, arg,
-                                                       ext_tcode);
+                                                       ext_tcode, flags);
                         } else {
                                 rcode = RCODE_TYPE_ERROR;
                         }
index 84f927925e5b65338fad891b0acc0fd78216079b..2a895b3a37ee2d7c1800c908cddd452967918945 100644 (file)
@@ -74,17 +74,22 @@ struct hpsb_address_ops {
          */
 
         /* These functions have to implement block reads for themselves. */
+        /* These functions either return a response code
+           or a negative number. In the first case a response will be generated; in the 
+           later case, no response will be sent and the driver, that handled the request
+           will send the response itself
+        */
         int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                     u64 addr, unsigned int length);
+                     u64 addr, unsigned int length, u16 flags);
         int (*write) (struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, unsigned int length);
+                     quadlet_t *data, u64 addr, unsigned int length, u16 flags);
 
         /* Lock transactions: write results of ext_tcode operation into
          * *store. */
         int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store,
-                     u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode);
+                     u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
         int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store,
-                       u64 addr, octlet_t data, octlet_t arg, int ext_tcode);
+                       u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
 };
 
 
@@ -94,14 +99,23 @@ void highlevel_add_host(struct hpsb_host *host);
 void highlevel_remove_host(struct hpsb_host *host);
 void highlevel_host_reset(struct hpsb_host *host);
 
+
+/* these functions are called to handle transactions. They are called, when
+   a packet arrives. The flags argument contains the second word of the first header
+   quadlet of the incoming packet (containing transaction label, retry code,
+   transaction code and priority). These functions either return a response code
+   or a negative number. In the first case a response will be generated; in the 
+   later case, no response will be sent and the driver, that handled the request
+   will send the response itself.
+*/
 int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                   u64 addr, unsigned int length);
+                   u64 addr, unsigned int length, u16 flags);
 int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
-                   quadlet_t *data, u64 addr, unsigned int length);
+                   quadlet_t *data, u64 addr, unsigned int length, u16 flags);
 int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode);
+                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode);
+                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
 
 void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data,
                            unsigned int length);
@@ -130,6 +144,8 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
 int hpsb_register_addrspace(struct hpsb_highlevel *hl,
                             struct hpsb_address_ops *ops, u64 start, u64 end);
 
+int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start);
+
 /*
  * Enable or disable receving a certain isochronous channel through the
  * iso_receive op.
index 62a5b753234724a6fcec7dc039986c22d9528fa2..9504458a429031a4b84f7990d92f392121f668cd 100644 (file)
@@ -138,7 +138,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra)
 
        atomic_set(&h->generation, 0);
 
-       INIT_TQUEUE(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
+       HPSB_INIT_WORK(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
 
         h->topology_map = h->csr.topology_map + 3;
         h->speed_map = (u8 *)(h->csr.speed_map + 2);
index ed5d6fdff96b0287cfe167479d6263726f184f6b..5169ce1ef06d4fdad6fcaa9b0fb10b06e8811289 100644 (file)
@@ -2,13 +2,20 @@
 #define _IEEE1394_HOSTS_H
 
 #include <linux/wait.h>
-#include <linux/tqueue.h>
 #include <linux/list.h>
 #include <asm/semaphore.h>
 
 #include "ieee1394_types.h"
 #include "csr.h"
 
+/* size of the array used to store config rom (in quadlets)
+   maximum is 0x100. About 0x40 is needed for the default
+   entries. So 0x80 should provide enough space for additional
+   directories etc. 
+   Note: All lowlevel drivers are required to allocate at least
+         this amount of memory for the configuration rom!
+*/
+#define CSR_CONFIG_ROM_SIZE       0x100
 
 struct hpsb_packet;
 
@@ -23,7 +30,7 @@ struct hpsb_host {
 
         struct list_head pending_packets;
         spinlock_t pending_pkt_lock;
-        struct tq_struct timeout_tq;
+        struct hpsb_queue_struct timeout_tq;
 
         /* A bitmask where a set bit means that this tlabel is in use.
          * FIXME - should be handled per node instead of per bus. */
@@ -119,7 +126,7 @@ struct hpsb_host_driver {
          * may not fail.  If any allocation is required, it must be done
          * earlier.
          */
-        size_t (*get_rom) (struct hpsb_host *host, const quadlet_t **pointer);
+        size_t (*get_rom) (struct hpsb_host *host, quadlet_t **pointer);
 
         /* This function shall implement packet transmission based on
          * packet->type.  It shall CRC both parts of the packet (unless
@@ -172,4 +179,24 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra);
 void hpsb_add_host(struct hpsb_host *host);
 void hpsb_remove_host(struct hpsb_host *h);
 
+/* updates the configuration rom of a host.
+ * rom_version must be the current version,
+ * otherwise it will fail with return value -1.
+ * Return value -2 indicates that the new
+ * rom version is too big.
+ * Return value 0 indicates success
+ */
+int hpsb_update_config_rom(struct hpsb_host *host,
+      const quadlet_t *new_rom, size_t size, unsigned char rom_version);
+
+/* reads the current version of the configuration rom of a host.
+ * buffersize is the size of the buffer, rom_size
+ * returns the size of the current rom image.
+ * rom_version is the version number of the fetched rom.
+ * return value -1 indicates, that the buffer was
+ * too small, 0 indicates success.
+ */
+int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
+      size_t buffersize, size_t *rom_size, unsigned char *rom_version);
+
 #endif /* _IEEE1394_HOSTS_H */
index 77ada1f2cf191b6a1c15301ade6f75b5ce3077ff..fad65a501b888f641eb6da9c9ded1a936e3c2878 100644 (file)
@@ -5,9 +5,19 @@
  *               highlevel or lowlevel code
  *
  * Copyright (C) 1999, 2000 Andreas E. Bombe
+ *                     2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
  *
  * This code is licensed under the GPL.  See the file COPYING in the root
  * directory of the kernel sources for details.
+ *
+ *
+ * Contributions:
+ *
+ * Manfred Weihs <weihs@ict.tuwien.ac.at>
+ *        loopback functionality in hpsb_send_packet
+ *        allow highlevel drivers to disable automatic response generation
+ *              and to generate responses themselves (deferred)
+ *
  */
 
 #include <linux/config.h>
@@ -19,7 +29,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/semaphore.h>
@@ -72,9 +81,10 @@ static void process_complete_tasks(struct hpsb_packet *packet)
        struct list_head *lh, *next;
 
        list_for_each_safe(lh, next, &packet->complete_tq) {
-               struct tq_struct *tq = list_entry(lh, struct tq_struct, list);
-               list_del(&tq->list);
-               schedule_task(tq);
+               struct hpsb_queue_struct *tq =
+                       list_entry(lh, struct hpsb_queue_struct, hpsb_queue_list);
+               list_del(&tq->hpsb_queue_list);
+               hpsb_schedule_work(tq);
        }
 
        return;
@@ -83,11 +93,11 @@ static void process_complete_tasks(struct hpsb_packet *packet)
 /**
  * hpsb_add_packet_complete_task - add a new task for when a packet completes
  * @packet: the packet whose completion we want the task added to
- * @tq: the tq_struct describing the task to add
+ * @tq: the hpsb_queue_struct describing the task to add
  */
-void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct tq_struct *tq)
+void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct hpsb_queue_struct *tq)
 {
-       list_add_tail(&tq->list, &packet->complete_tq);
+       list_add_tail(&tq->hpsb_queue_list, &packet->complete_tq);
        return;
 }
 
@@ -372,12 +382,19 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
                 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
         /* irm_id is kept up to date by check_selfids() */
         if (host->irm_id == host->node_id) {
                 host->is_irm = 1;
                 host->is_busmgr = 1;
                 host->busmgr_id = host->node_id;
                 host->csr.bus_manager_id = host->node_id;
+        } else {
+                host->is_busmgr = 0;
+                host->is_irm = 0;
         }
 
         host->reset_retries = 0;
@@ -420,7 +437,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
         up(&packet->state_change);
-        schedule_task(&host->timeout_tq);
+        hpsb_schedule_work(&host->timeout_tq);
 }
 
 /**
@@ -448,6 +465,45 @@ int hpsb_send_packet(struct hpsb_packet *packet)
 
         packet->state = hpsb_queued;
 
+        if (packet->node_id == host->node_id)
+        { /* it is a local request, so handle it locally */
+                quadlet_t *data;
+                size_t size=packet->data_size+packet->header_size;
+
+                int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+                data = kmalloc(packet->header_size + packet->data_size, kmflags);
+                if (!data) {
+                        HPSB_ERR("unable to allocate memory for concatenating header and data");
+                        return 0;
+                }
+
+                memcpy(data, packet->header, packet->header_size);
+
+                if (packet->data_size)
+                {
+                        if (packet->data_be) {
+                                memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
+                        } else {
+                                int i;
+                                quadlet_t *my_data=(quadlet_t*) ((u8*) data + packet->data_size);
+                                for (i=0; i < packet->data_size/4; i++) {
+                                        my_data[i] = cpu_to_be32(packet->data[i]);
+                                }
+                        }
+                }
+
+#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);
+
+                kfree(data);
+
+                return 1;
+        }
+
         if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
                 packet->speed_code =
                         host->speed_map[(host->node_id & NODE_MASK) * 64
@@ -600,8 +656,10 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
 {
         struct hpsb_packet *packet;
         int length, rcode, extcode;
+        quadlet_t buffer;
         nodeid_t source = data[1] >> 16;
-       nodeid_t dest = data[0] >> 16;
+        nodeid_t dest = data[0] >> 16;
+        u16 flags = (u16) data[0];
         u64 addr;
 
         /* big FIXME - no error checking is done for an out of bounds length */
@@ -610,10 +668,11 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
         case TCODE_WRITEQ:
                 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
                 rcode = highlevel_write(host, source, dest, data+3,
-                                       addr, 4);
+                                       addr, 4, flags);
 
                 if (!write_acked
-                    && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
                         fill_async_write_resp(packet, rcode);
@@ -624,10 +683,11 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
         case TCODE_WRITEB:
                 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
                 rcode = highlevel_write(host, source, dest, data+4,
-                                       addr, data[3]>>16);
+                                       addr, data[3]>>16, flags);
 
                 if (!write_acked
-                    && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
                         fill_async_write_resp(packet, rcode);
@@ -636,12 +696,14 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                 break;
 
         case TCODE_READQ:
-                PREP_REPLY_PACKET(0);
-
                 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-                rcode = highlevel_read(host, source, data, addr, 4);
-                fill_async_readquad_resp(packet, rcode, *data);
-                send_packet_nocare(packet);
+                rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
+
+                if (rcode >= 0) {
+                        PREP_REPLY_PACKET(0);
+                        fill_async_readquad_resp(packet, rcode, buffer);
+                        send_packet_nocare(packet);
+                }
                 break;
 
         case TCODE_READB:
@@ -650,9 +712,12 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
 
                 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
                 rcode = highlevel_read(host, source, packet->data, addr,
-                                       length);
-                fill_async_readblock_resp(packet, rcode, length);
-                send_packet_nocare(packet);
+                                       length, flags);
+
+                if (rcode >= 0) {
+                        fill_async_readblock_resp(packet, rcode, length);
+                        send_packet_nocare(packet);
+                }
                 break;
 
         case TCODE_LOCK_REQUEST:
@@ -670,7 +735,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                 switch (length) {
                 case 4:
                         rcode = highlevel_lock(host, source, packet->data, addr,
-                                               data[4], 0, extcode);
+                                               data[4], 0, extcode,flags);
                         fill_async_lock_resp(packet, rcode, extcode, 4);
                         break;
                 case 8:
@@ -679,13 +744,13 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                                 rcode = highlevel_lock(host, source,
                                                        packet->data, addr,
                                                        data[5], data[4], 
-                                                       extcode);
+                                                       extcode, flags);
                                 fill_async_lock_resp(packet, rcode, extcode, 4);
                         } else {
                                 rcode = highlevel_lock64(host, source,
                                              (octlet_t *)packet->data, addr,
                                              *(octlet_t *)(data + 4), 0ULL,
-                                             extcode);
+                                             extcode, flags);
                                 fill_async_lock_resp(packet, rcode, extcode, 8);
                         }
                         break;
@@ -694,15 +759,20 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                                                  (octlet_t *)packet->data, addr,
                                                  *(octlet_t *)(data + 6),
                                                  *(octlet_t *)(data + 4), 
-                                                 extcode);
+                                                 extcode, flags);
                         fill_async_lock_resp(packet, rcode, extcode, 8);
                         break;
                 default:
-                        fill_async_lock_resp(packet, RCODE_TYPE_ERROR,
+                        rcode = RCODE_TYPE_ERROR;
+                        fill_async_lock_resp(packet, rcode,
                                              extcode, 0);
                 }
 
-                send_packet_nocare(packet);
+                if (rcode >= 0) {
+                        send_packet_nocare(packet);
+                } else {
+                        free_hpsb_packet(packet);
+                }
                 break;
         }
 
@@ -811,7 +881,7 @@ void abort_timedouts(struct hpsb_host *host)
         }
 
         if (!list_empty(&host->pending_packets))
-               schedule_task(&host->timeout_tq);
+               hpsb_schedule_work(&host->timeout_tq);
 
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
@@ -1109,6 +1179,7 @@ EXPORT_SYMBOL(hpsb_make_readbpacket);
 EXPORT_SYMBOL(hpsb_make_writeqpacket);
 EXPORT_SYMBOL(hpsb_make_writebpacket);
 EXPORT_SYMBOL(hpsb_make_lockpacket);
+EXPORT_SYMBOL(hpsb_make_lock64packet);
 EXPORT_SYMBOL(hpsb_make_phypacket);
 EXPORT_SYMBOL(hpsb_packet_success);
 EXPORT_SYMBOL(hpsb_make_packet);
@@ -1119,6 +1190,7 @@ EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_register_highlevel);
 EXPORT_SYMBOL(hpsb_unregister_highlevel);
 EXPORT_SYMBOL(hpsb_register_addrspace);
+EXPORT_SYMBOL(hpsb_unregister_addrspace);
 EXPORT_SYMBOL(hpsb_listen_channel);
 EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(highlevel_read);
@@ -1135,6 +1207,8 @@ EXPORT_SYMBOL(hpsb_node_fill_packet);
 EXPORT_SYMBOL(hpsb_node_read);
 EXPORT_SYMBOL(hpsb_node_write);
 EXPORT_SYMBOL(hpsb_node_lock);
+EXPORT_SYMBOL(hpsb_update_config_rom);
+EXPORT_SYMBOL(hpsb_get_config_rom);
 EXPORT_SYMBOL(hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
 EXPORT_SYMBOL(hpsb_release_unit_directory);
index d62ff3e4b42d21343f606ce2fbc87a58b3a6ef15..dc33c7199d7bd7a4f9e4ea08bc1d329d64204719 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _IEEE1394_CORE_H
 #define _IEEE1394_CORE_H
 
-#include <linux/tqueue.h>
 #include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/proc_fs.h>
@@ -78,7 +77,7 @@ struct hpsb_packet {
 };
 
 /* add a new task for when a packet completes */
-void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct tq_struct *tq);
+void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct hpsb_queue_struct *tq);
 
 static inline struct hpsb_packet *driver_packet(struct list_head *l)
 {
index c153cb72446351b44a6170928e4c92dfc53fdb78..9733e5454f1de4a7874ff7c446c4caf89295f4e0 100644 (file)
@@ -297,14 +297,6 @@ int hpsb_packet_success(struct hpsb_packet *packet)
         HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
 }
 
-
-int hpsb_read_trylocal(struct hpsb_host *host, nodeid_t node, u64 addr, 
-                       quadlet_t *buffer, size_t length)
-{
-        if (host->node_id != node) return -1;
-        return highlevel_read(host, node, buffer, addr, length);
-}
-
 struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node,
                                           u64 addr)
 {
@@ -400,6 +392,31 @@ struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
         return p;
 }
 
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
+                                           u64 addr, int extcode)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(16);
+        if (!p) return NULL;
+
+        p->host = host;
+        p->tlabel = get_tlabel(host, node, 1);
+        p->node_id = node;
+
+        switch (extcode) {
+        case EXTCODE_FETCH_ADD:
+        case EXTCODE_LITTLE_ADD:
+                fill_async_lock(p, addr, extcode, 8);
+                break;
+        default:
+                fill_async_lock(p, addr, extcode, 16);
+                break;
+        }
+
+        return p;
+}
+
 struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
                                         quadlet_t data) 
 {
@@ -429,18 +446,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
                 return -EINVAL;
         }
 
-        if (host->node_id == node) {
-                switch(highlevel_read(host, node, buffer, addr, length)) {
-                case RCODE_COMPLETE:
-                        return 0;
-                case RCODE_TYPE_ERROR:
-                        return -EACCES;
-                case RCODE_ADDRESS_ERROR:
-                default:
-                        return -EINVAL;
-                }
-        }
-
         if (length == 4) {
                 packet = hpsb_make_readqpacket(host, node, addr);
         } else {
@@ -509,18 +514,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
        if (length == 0)
                return -EINVAL;
 
-       if (host->node_id == node) {
-               switch(highlevel_write(host, node, node, buffer, addr, length)) {
-               case RCODE_COMPLETE:
-                       return 0;
-               case RCODE_TYPE_ERROR:
-                       return -EACCES;
-               case RCODE_ADDRESS_ERROR:
-               default:
-                       return -EINVAL;
-               }
-       }
-
        packet = hpsb_make_packet (host, node, addr, buffer, length);
 
        if (!packet)
@@ -551,19 +544,6 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
         struct hpsb_packet *packet;
         int retval = 0, length;
         
-        if (host->node_id == node) {
-                switch(highlevel_lock(host, node, data, addr, *data, arg,
-                                      extcode)) {
-                case RCODE_COMPLETE:
-                        return 0;
-                case RCODE_TYPE_ERROR:
-                        return -EACCES;
-                case RCODE_ADDRESS_ERROR:
-                default:
-                        return -EINVAL;
-                }
-        }
-
         packet = alloc_hpsb_packet(8);
         if (!packet) {
                 return -ENOMEM;
index 724a5fe5e7cf43189ed1e08effb5152c9ce1f4d5..47ad22239fc6d931cc3b8f9fcad966c2ba33905b 100644 (file)
@@ -42,6 +42,8 @@ struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
                                            size_t length);
 struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
                                          u64 addr, int extcode);
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
+                                          u64 addr, int extcode);
 struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
                                         quadlet_t data) ;
 
index d5ce71d9dcfa962910359e9d37c355fd8f681fed..d30396111db1dcc2d123ee4be33e9368fdba03bf 100644 (file)
 #define __devexit_p(x) x
 #endif
 
-/* This showed up around this time */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12)
-
-# ifndef MODULE_LICENSE
-# define MODULE_LICENSE(x)
-# endif
-
-# ifndef min
-# define min(x,y) ({ \
-       const typeof(x) _x = (x);       \
-       const typeof(y) _y = (y);       \
-       (void) (&_x == &_y);            \
-       _x < _y ? _x : _y; })
-# endif
-
-#endif /* Linux version < 2.4.12 */
-
 #include <linux/spinlock.h>
 
 #ifndef list_for_each_safe
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #endif
 
+
+/* Compatibility for task/work queues */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,42)
+/* Use task queue */
+#include <linux/tqueue.h>
+#define hpsb_queue_struct tq_struct
+#define hpsb_queue_list list
+#define hpsb_schedule_work(x) schedule_task(x)
+#define HPSB_INIT_WORK(x,y,z) INIT_TQUEUE(x,y,z)
+#define HPSB_PREPARE_WORK(x,y,z) PREPARE_TQUEUE(x,y,z)
+#else
+/* Use work queue */
+#include <linux/workqueue.h>
+#define hpsb_queue_struct work_struct
+#define hpsb_queue_list entry
+#define hpsb_schedule_work(x) schedule_work(x)
+#define HPSB_INIT_WORK(x,y,z) INIT_WORK(x,y,z)
+#define HPSB_PREPARE_WORK(x,y,z) PREPARE_WORK(x,y,z)
+#endif
+
+
 typedef u32 quadlet_t;
 typedef u64 octlet_t;
 typedef u16 nodeid_t;
 
+typedef u8  byte_t;
+typedef u64 nodeaddr_t;
+typedef u16 arm_length_t;
+
 #define BUS_MASK  0xffc0
 #define NODE_MASK 0x003f
 #define LOCAL_BUS 0xffc0
index 3504e3075aa8426fad813d57e13e21e8a10fcc5d..7f089d750b58d2af0865f0220b1b88bc088f9d0f 100644 (file)
@@ -91,7 +91,6 @@
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
-#include <linux/tqueue.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 
@@ -154,7 +153,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-       "$Rev: 578 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 601 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(attempt_root,"i");
@@ -1905,7 +1904,7 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
        ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu;
 }
 
-static size_t ohci_get_rom(struct hpsb_host *host, const quadlet_t **ptr)
+static size_t ohci_get_rom(struct hpsb_host *host, quadlet_t **ptr)
 {
        struct ti_ohci *ohci=host->hostdata;
 
index e5b69b6f532b5de01cfa01ff985023203d9c054c..96b9e24c0625b7274e9a76fd91daf7156957e4a1 100644 (file)
@@ -1677,7 +1677,7 @@ static int __devinit add_card(struct pci_dev *dev,
 
 
 
-static size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr)
+static size_t get_lynx_rom(struct hpsb_host *host, quadlet_t **ptr)
 {
         struct ti_lynx *lynx = host->hostdata;
         *ptr = lynx->config_rom;
index 6b850e688628eedc285cd381c49de5b6ce453180..61b80b485dcd86c0ba3920af3d1be7564d551f89 100644 (file)
@@ -4,9 +4,27 @@
  * Raw interface to the bus
  *
  * Copyright (C) 1999, 2000 Andreas E. Bombe
+ *               2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
+ *                     2002 Christian Toegel <christian.toegel@gmx.at>
  *
  * This code is licensed under the GPL.  See the file COPYING in the root
  * directory of the kernel sources for details.
+ *
+ *
+ * Contributions:
+ *
+ * Manfred Weihs <weihs@ict.tuwien.ac.at>
+ *        configuration ROM manipulation
+ *        address range mapping
+ *        adaptation for new (transparent) loopback mechanism
+ *        sending of arbitrary async packets
+ * Christian Toegel <christian.toegel@gmx.at>
+ *        address range mapping
+ *        lock64 request
+ *        transmit physical packet
+ *        busreset notification control (switch on/off)
+ *        busreset with selection of type (short/long)
+ *        request_reply
  */
 
 #include <linux/kernel.h>
 #define ptr2int(x) ((u64)(u32)x)
 #endif
 
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+#define RAW1394_DEBUG
+#endif
+
+#ifdef RAW1394_DEBUG
+#define DBGMSG(fmt, args...) \
+printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
+#else
+#define DBGMSG(fmt, args...)
+#endif
 
 static devfs_handle_t devfs_handle;
 
@@ -53,6 +81,21 @@ static struct hpsb_highlevel *hl_handle;
 static atomic_t iso_buffer_size;
 static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
 
+static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
+             u64 addr, unsigned int length, u16 flags);
+static int arm_write (struct hpsb_host *host, int nodeid, int destid,
+              quadlet_t *data, u64 addr, unsigned int length, u16 flags);
+static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
+             u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
+static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
+               u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
+static struct hpsb_address_ops arm_ops = {
+        read:     arm_read,
+        write:    arm_write,
+        lock:     arm_lock,
+        lock64:   arm_lock64,
+};
+
 static void queue_complete_cb(struct pending_request *req);
 
 static struct pending_request *__alloc_pending_request(int flags)
@@ -64,7 +107,7 @@ static struct pending_request *__alloc_pending_request(int flags)
         if (req != NULL) {
                 memset(req, 0, sizeof(struct pending_request));
                 INIT_LIST_HEAD(&req->list);
-               INIT_TQUEUE(&req->tq, (void(*)(void*))queue_complete_cb, NULL);
+                HPSB_INIT_WORK(&req->tq, (void(*)(void*))queue_complete_cb, NULL);
         }
 
         return req;
@@ -128,7 +171,8 @@ static void queue_complete_cb(struct pending_request *req)
                 req->req.length = 0;
         }
 
-        free_tlabel(packet->host, packet->node_id, packet->tlabel);
+        if (req->req.type != RAW1394_REQ_PHYPACKET)
+                free_tlabel(packet->host, packet->node_id, packet->tlabel);
 
         queue_complete_req(req);
 }
@@ -137,6 +181,7 @@ static void queue_complete_cb(struct pending_request *req)
 static void add_host(struct hpsb_host *host)
 {
         struct host_info *hi;
+        unsigned long flags;
 
         hi = (struct host_info *)kmalloc(sizeof(struct host_info), SLAB_KERNEL);
         if (hi != NULL) {
@@ -144,10 +189,10 @@ static void add_host(struct hpsb_host *host)
                 hi->host = host;
                 INIT_LIST_HEAD(&hi->file_info_list);
 
-                spin_lock_irq(&host_info_lock);
+                spin_lock_irqsave(&host_info_lock, flags);
                 list_add_tail(&hi->list, &host_info_list);
                 host_count++;
-                spin_unlock_irq(&host_info_lock);
+                spin_unlock_irqrestore(&host_info_lock, flags);
         }
 
         atomic_inc(&internal_generation);
@@ -172,15 +217,22 @@ static struct host_info *find_host_info(struct hpsb_host *host)
 static void remove_host(struct hpsb_host *host)
 {
         struct host_info *hi;
+        unsigned long flags;
 
-        spin_lock_irq(&host_info_lock);
+        spin_lock_irqsave(&host_info_lock, flags);
         hi = find_host_info(host);
 
         if (hi != NULL) {
                 list_del(&hi->list);
                 host_count--;
+                /* 
+                   FIXME: adressranges should be removed 
+                   and fileinfo states should be initialized
+                   (including setting generation to 
+                   internal-generation ...)
+                */
         }
-        spin_unlock_irq(&host_info_lock);
+        spin_unlock_irqrestore(&host_info_lock, flags);
 
         if (hi == NULL) {
                 printk(KERN_ERR "raw1394: attempt to remove unknown host "
@@ -207,20 +259,22 @@ static void host_reset(struct hpsb_host *host)
         if (hi != NULL) {
                 list_for_each(lh, &hi->file_info_list) {
                         fi = list_entry(lh, struct file_info, list);
-                        req = __alloc_pending_request(SLAB_ATOMIC);
-
-                        if (req != NULL) {
-                                req->file_info = fi;
-                                req->req.type = RAW1394_REQ_BUS_RESET;
-                                req->req.generation = get_hpsb_generation(host);
-                                req->req.misc = (host->node_id << 16)
-                                        | host->node_count;
-                                if (fi->protocol_version > 3) {
-                                        req->req.misc |= ((host->irm_id
-                                                           & NODE_MASK) << 8);
+                        if (fi->notification == RAW1394_NOTIFY_ON) {
+                                req = __alloc_pending_request(SLAB_ATOMIC);
+
+                                if (req != NULL) {
+                                        req->file_info = fi;
+                                        req->req.type = RAW1394_REQ_BUS_RESET;
+                                        req->req.generation = get_hpsb_generation(host);
+                                        req->req.misc = (host->node_id << 16)
+                                                | host->node_count;
+                                        if (fi->protocol_version > 3) {
+                                                req->req.misc |= ((host->irm_id
+                                                                   & NODE_MASK) << 8);
+                                        }
+
+                                        queue_complete_req(req);
                                 }
-
-                                queue_complete_req(req);
                         }
                 }
         }
@@ -529,7 +583,7 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
 {
         int channel = req->req.misc;
 
-        spin_lock(&host_info_lock);
+        spin_lock_irq(&host_info_lock);
         if ((channel > 63) || (channel < -64)) {
                 req->req.error = RAW1394_ERROR_INVALID_ARG;
         } else if (channel >= 0) {
@@ -556,7 +610,7 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
 
         req->req.length = 0;
         queue_complete_req(req);
-        spin_unlock(&host_info_lock);
+        spin_unlock_irq(&host_info_lock);
 }
 
 static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -579,84 +633,9 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
         queue_complete_req(req);
 }
 
-static int handle_local_request(struct file_info *fi,
-                                struct pending_request *req, int node)
-{
-        u64 addr = req->req.address & 0xffffffffffffULL;
-
-        req->data = kmalloc(req->req.length, SLAB_KERNEL);
-        if (!req->data) return -ENOMEM;
-        req->free_data = 1;
-
-        switch (req->req.type) {
-        case RAW1394_REQ_ASYNC_READ:
-                req->req.error = highlevel_read(fi->host, node, req->data, addr,
-                                                req->req.length);
-                break;
-
-        case RAW1394_REQ_ASYNC_WRITE:
-                if (copy_from_user(req->data, int2ptr(req->req.sendb),
-                                   req->req.length)) {
-                        req->req.error = RAW1394_ERROR_MEMFAULT;
-                        break;
-                }
 
-                req->req.error = highlevel_write(fi->host, node, node, req->data,
-                                                 addr, req->req.length);
-                req->req.length = 0;
-                break;
-
-        case RAW1394_REQ_LOCK:
-                if ((req->req.misc == EXTCODE_FETCH_ADD)
-                    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                        if (req->req.length != 4) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                } else {
-                        if (req->req.length != 8) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                }
-
-                if (copy_from_user(req->data, int2ptr(req->req.sendb),
-                                   req->req.length)) {
-                        req->req.error = RAW1394_ERROR_MEMFAULT;
-                        break;
-                }
-
-                if (req->req.length == 8) {
-                        req->req.error = highlevel_lock(fi->host, node,
-                                                        req->data, addr,
-                                                        req->data[1],
-                                                        req->data[0],
-                                                        req->req.misc);
-                        req->req.length = 4;
-                } else {
-                        req->req.error = highlevel_lock(fi->host, node,
-                                                        req->data, addr,
-                                                        req->data[0], 0,
-                                                        req->req.misc);
-                }
-                break;
-
-        case RAW1394_REQ_LOCK64:
-        default:
-                req->req.error = RAW1394_ERROR_STATE_ORDER;
-        }
-
-        if (req->req.error)
-                req->req.length = 0;
-        if (req->req.error >= 0)
-                req->req.error |= ACK_PENDING << 16;
-
-        queue_complete_req(req);
-        return sizeof(struct raw1394_request);
-}
-
-static int handle_remote_request(struct file_info *fi,
-                                 struct pending_request *req, int node)
+static int handle_async_request(struct file_info *fi,
+                                struct pending_request *req, int node)
 {
         struct hpsb_packet *packet = NULL;
         u64 addr = req->req.address & 0xffffffffffffULL;
@@ -664,11 +643,13 @@ static int handle_remote_request(struct file_info *fi,
         switch (req->req.type) {
         case RAW1394_REQ_ASYNC_READ:
                 if (req->req.length == 4) {
+                        DBGMSG("quadlet_read_request called");        
                         packet = hpsb_make_readqpacket(fi->host, node, addr);
                         if (!packet) return -ENOMEM;
 
                         req->data = &packet->header[3];
                 } else {
+                        DBGMSG("block_read_request called");
                         packet = hpsb_make_readbpacket(fi->host, node, addr,
                                                        req->req.length);
                         if (!packet) return -ENOMEM;
@@ -681,6 +662,7 @@ static int handle_remote_request(struct file_info *fi,
                 if (req->req.length == 4) {
                         quadlet_t x;
 
+                        DBGMSG("quadlet_write_request called");
                         if (copy_from_user(&x, int2ptr(req->req.sendb), 4)) {
                                 req->req.error = RAW1394_ERROR_MEMFAULT;
                         }
@@ -689,6 +671,7 @@ static int handle_remote_request(struct file_info *fi,
                                                         x);
                         if (!packet) return -ENOMEM;
                 } else {
+                        DBGMSG("block_write_request called");
                         packet = hpsb_make_writebpacket(fi->host, node, addr,
                                                         req->req.length);
                         if (!packet) return -ENOMEM;
@@ -702,6 +685,7 @@ static int handle_remote_request(struct file_info *fi,
                 break;
 
         case RAW1394_REQ_LOCK:
+                DBGMSG("lock_request called");
                 if ((req->req.misc == EXTCODE_FETCH_ADD)
                     || (req->req.misc == EXTCODE_LITTLE_ADD)) {
                         if (req->req.length != 4) {
@@ -730,6 +714,33 @@ static int handle_remote_request(struct file_info *fi,
                 break;
 
         case RAW1394_REQ_LOCK64:
+                DBGMSG("lock64_request called");
+                if ((req->req.misc == EXTCODE_FETCH_ADD)
+                    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
+                        if (req->req.length != 8) {
+                                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                                break;
+                        }
+                } else {
+                        if (req->req.length != 16) {
+                                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                                break;
+                        }
+                }
+                packet = hpsb_make_lock64packet(fi->host, node, addr,
+                                                req->req.misc);
+                if (!packet) return -ENOMEM;
+
+                if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+                                   req->req.length)) {
+                        req->req.error = RAW1394_ERROR_MEMFAULT;
+                        break;
+                }
+
+                req->data = packet->data;
+                req->req.length = 8;
+                break;
+
         default:
                 req->req.error = RAW1394_ERROR_STATE_ORDER;
         }
@@ -783,8 +794,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
                 return sizeof(struct raw1394_request);
         }
 
-        req->tq.data = req;
-        req->tq.routine = (void (*)(void*))queue_complete_req;
+       HPSB_PREPARE_WORK(&req->tq, (void (*)(void*))queue_complete_req, req);
         req->req.length = 0;
        hpsb_add_packet_complete_task(packet, &req->tq);
 
@@ -803,25 +813,1092 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
         return sizeof(struct raw1394_request);
 }
 
-static int state_connected(struct file_info *fi, struct pending_request *req)
+static int handle_async_send(struct file_info *fi, struct pending_request *req)
 {
-        int node = req->req.address >> 48;
+        struct hpsb_packet *packet;
+        int header_length = req->req.misc & 0xffff;
+        int expect_response = req->req.misc >> 16;
 
-        req->req.error = RAW1394_ERROR_NONE;
+        if ((header_length > req->req.length) ||
+            (header_length  < 12))
+        {
+                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                req->req.length = 0;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+        } 
 
-        if (req->req.type ==  RAW1394_REQ_ISO_SEND) {
-                return handle_iso_send(fi, req, node);
+        packet = alloc_hpsb_packet(req->req.length-header_length);
+        req->packet = packet;
+        if (!packet) return -ENOMEM;
+
+        if (copy_from_user(packet->header, int2ptr(req->req.sendb),
+                           header_length)) {
+                req->req.error = RAW1394_ERROR_MEMFAULT;
+                req->req.length = 0;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
         }
 
-        if (req->req.generation != get_hpsb_generation(fi->host)) {
-                req->req.error = RAW1394_ERROR_GENERATION;
-                req->req.generation = get_hpsb_generation(fi->host);
+        if (copy_from_user(packet->data, ((u8*) int2ptr(req->req.sendb)) + header_length,
+                           packet->data_size)) {
+                req->req.error = RAW1394_ERROR_MEMFAULT;
                 req->req.length = 0;
                 queue_complete_req(req);
                 return sizeof(struct raw1394_request);
         }
 
+        packet->type = hpsb_async;
+        packet->node_id = packet->header[0] >> 16;
+        packet->tcode = (packet->header[0] >> 4) & 0xf;
+        packet->tlabel = (packet->header[0] >> 10) &0x3f;
+        packet->host = fi->host;
+        packet->expect_response = expect_response;
+        packet->header_size=header_length;
+        packet->data_size=req->req.length-header_length;
+
+       HPSB_PREPARE_WORK(&req->tq, (void (*)(void*))queue_complete_req, req);
+        req->req.length = 0;
+        hpsb_add_packet_complete_task(packet, &req->tq);
+
+        spin_lock_irq(&fi->reqlists_lock);
+        list_add_tail(&req->list, &fi->req_pending);
+        spin_unlock_irq(&fi->reqlists_lock);
+
+        /* Update the generation of the packet just before sending. */
+        packet->generation = get_hpsb_generation(fi->host);
+
+        if (!hpsb_send_packet(packet)) {
+                req->req.error = RAW1394_ERROR_SEND_ERROR;
+                queue_complete_req(req);
+        }
+
+        return sizeof(struct raw1394_request);
+}
+
+static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
+             u64 addr, unsigned int length, u16 flags)
+{
+        struct pending_request *req;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi = NULL;
+        struct list_head *entry;
+        struct arm_addr  *arm_addr = NULL;
+        struct arm_request  *arm_req = NULL;
+        struct arm_response *arm_resp = NULL;
+        int found=0, size=0, rcode=-1;
+        struct arm_request_response *arm_req_resp = NULL;
+
+        DBGMSG("arm_read  called by node: %X"
+              "addr: %4.4x %8.8x length: %u", nodeid,
+              (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+              length);
+        spin_lock(&host_info_lock);
+        hi = find_host_info(host); /* search address-entry */
+        if (hi != NULL) {
+                list_for_each(lh, &hi->file_info_list) {
+                        fi = list_entry(lh, struct file_info, list);
+                        entry = fi->addr_list.next;
+                        while (entry != &(fi->addr_list)) {
+                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                                if (((arm_addr->start) <= (addr)) && 
+                                        ((arm_addr->end) >= (addr+length))) {
+                                        found = 1;
+                                        break;
+                                }
+                                entry = entry->next;
+                        }
+                        if (found) {
+                                break;
+                        }
+                }
+        }
+        rcode = -1;
+        if (!found) {
+                printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
+                " -> rcode_address_error\n");
+                spin_unlock(&host_info_lock);
+                return (RCODE_ADDRESS_ERROR);
+        } else {
+                DBGMSG("arm_read addr_entry FOUND");
+        }
+        if (arm_addr->rec_length < length) {
+                DBGMSG("arm_read blocklength too big -> rcode_data_error");
+                rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
+        }
+        if (rcode == -1) {
+                if (arm_addr->access_rights & ARM_READ) {
+                        if (!(arm_addr->client_transactions & ARM_READ)) {
+                                memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), 
+                                       length);
+                                DBGMSG("arm_read -> (rcode_complete)");
+                                rcode = RCODE_COMPLETE;
+                        }
+                } else {
+                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                        DBGMSG("arm_read -> rcode_type_error (access denied)");
+                }
+        }
+        if (arm_addr->notification_options & ARM_READ) {
+                DBGMSG("arm_read -> entering notification-section");
+                req = __alloc_pending_request(SLAB_ATOMIC);
+                if (!req) {
+                        DBGMSG("arm_read -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                if (rcode == RCODE_COMPLETE) {
+                        size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
+                                length * sizeof(byte_t) +
+                                sizeof (struct arm_request_response);
+                } else {
+                        size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
+                                sizeof (struct arm_request_response);
+                }
+                req->data = kmalloc(size, SLAB_ATOMIC);
+                if (!(req->data)) {
+                        free_pending_request(req);
+                        DBGMSG("arm_read -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                req->free_data=1;
+                req->file_info = fi;
+                req->req.type = RAW1394_REQ_ARM;
+                req->req.generation = get_hpsb_generation(host);
+                req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
+                req->req.tag  = arm_addr->arm_tag;
+                req->req.recvb = arm_addr->recvb;
+                req->req.length = size;
+                arm_req_resp = (struct arm_request_response *) (req->data);
+                arm_req  = (struct arm_request *) ((byte_t *)(req->data) + 
+                        (sizeof (struct arm_request_response)));
+                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + 
+                        (sizeof(struct arm_request)));
+                arm_req->buffer  = NULL;
+                arm_resp->buffer = NULL;
+                if (rcode == RCODE_COMPLETE) {
+                        arm_resp->buffer = ((byte_t *)(arm_resp) + 
+                                (sizeof(struct arm_response)));
+                        memcpy (arm_resp->buffer,
+                                (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), 
+                                length);
+                        arm_resp->buffer = int2ptr((arm_addr->recvb) + 
+                                sizeof (struct arm_request_response) +
+                                sizeof (struct arm_request) +
+                                sizeof (struct arm_response));
+                }
+                arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0;
+                arm_resp->response_code = rcode;
+                arm_req->buffer_length = 0;
+                arm_req->generation = req->req.generation;
+                arm_req->extended_transaction_code = 0;
+                arm_req->destination_offset = addr;
+                arm_req->source_nodeid = nodeid;
+                arm_req->destination_nodeid = host->node_id;
+                arm_req->tlabel = (flags >> 10) & 0x3f;
+                arm_req->tcode = (flags >> 4) & 0x0f;
+                arm_req_resp->request  = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response));
+                arm_req_resp->response = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request));
+                queue_complete_req(req);
+        }
+        spin_unlock(&host_info_lock);
+        return(rcode);
+}
+
+static int arm_write (struct hpsb_host *host, int nodeid, int destid,
+              quadlet_t *data, u64 addr, unsigned int length, u16 flags)
+{
+        struct pending_request *req;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi = NULL;
+        struct list_head *entry;
+        struct arm_addr  *arm_addr = NULL;
+        struct arm_request  *arm_req = NULL;
+        struct arm_response *arm_resp = NULL;        
+        int found=0, size=0, rcode=-1, length_conflict=0;
+        struct arm_request_response *arm_req_resp = NULL;
+
+        DBGMSG("arm_write called by node: %X"
+              "addr: %4.4x %8.8x length: %u", nodeid,
+              (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+              length);
+        spin_lock(&host_info_lock);
+        hi = find_host_info(host); /* search address-entry */
+        if (hi != NULL) {
+                list_for_each(lh, &hi->file_info_list) {
+                        fi = list_entry(lh, struct file_info, list);
+                        entry = fi->addr_list.next;
+                        while (entry != &(fi->addr_list)) {
+                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                                if (((arm_addr->start) <= (addr)) && 
+                                        ((arm_addr->end) >= (addr+length))) {
+                                        found = 1;
+                                        break;
+                                }
+                                entry = entry->next;
+                        }
+                        if (found) {
+                                break;
+                        }
+                }
+        }
+        rcode = -1;
+        if (!found) {
+                printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
+                " -> rcode_address_error\n");
+                spin_unlock(&host_info_lock);
+                return (RCODE_ADDRESS_ERROR);
+        } else {
+                DBGMSG("arm_write addr_entry FOUND");
+        }
+        if (arm_addr->rec_length < length) {
+                DBGMSG("arm_write blocklength too big -> rcode_data_error");
+                length_conflict = 1;
+                rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
+        }
+        if (rcode == -1) {
+                if (arm_addr->access_rights & ARM_WRITE) {
+                        if (!(arm_addr->client_transactions & ARM_WRITE)) {
+                                memcpy((arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
+                                        data, length);
+                                DBGMSG("arm_write -> (rcode_complete)");
+                                rcode = RCODE_COMPLETE;
+                        }
+                } else {
+                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                        DBGMSG("arm_write -> rcode_type_error (access denied)");
+                }
+        }
+        if (arm_addr->notification_options & ARM_WRITE) {
+                DBGMSG("arm_write -> entering notification-section");
+                req = __alloc_pending_request(SLAB_ATOMIC);
+                if (!req) {
+                        DBGMSG("arm_write -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request my be retried */
+                }
+                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
+                        (length) * sizeof(byte_t) +
+                        sizeof (struct arm_request_response);
+                req->data = kmalloc(size, SLAB_ATOMIC);
+                if (!(req->data)) {
+                        free_pending_request(req);
+                        DBGMSG("arm_write -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                req->free_data=1;
+                req->file_info = fi;
+                req->req.type = RAW1394_REQ_ARM;
+                req->req.generation = get_hpsb_generation(host);
+                req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
+                req->req.tag  = arm_addr->arm_tag;
+                req->req.recvb = arm_addr->recvb;
+                req->req.length = size;
+                arm_req_resp = (struct arm_request_response *) (req->data);
+                arm_req  = (struct arm_request *) ((byte_t *)(req->data) + 
+                        (sizeof (struct arm_request_response)));
+                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + 
+                        (sizeof(struct arm_request)));
+                arm_req->buffer = ((byte_t *)(arm_resp) + 
+                        (sizeof(struct arm_response)));
+                arm_resp->buffer = NULL;
+                memcpy (arm_req->buffer, data, length);
+                arm_req->buffer = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request) +
+                        sizeof (struct arm_response));
+                arm_req->buffer_length = length;
+                arm_req->generation = req->req.generation;
+                arm_req->extended_transaction_code = 0;
+                arm_req->destination_offset = addr;
+                arm_req->source_nodeid = nodeid;
+                arm_req->destination_nodeid = destid;
+                arm_req->tlabel = (flags >> 10) & 0x3f;
+                arm_req->tcode = (flags >> 4) & 0x0f;
+                arm_resp->buffer_length = 0;
+                arm_resp->response_code = rcode;
+                arm_req_resp->request  = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response));
+                arm_req_resp->response = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request));
+                queue_complete_req(req);
+        }
+        spin_unlock(&host_info_lock);
+        return(rcode);
+}
+
+static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
+             u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
+{
+        struct pending_request *req;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi = NULL;
+        struct list_head *entry;
+        struct arm_addr  *arm_addr = NULL;
+        struct arm_request  *arm_req = NULL;
+        struct arm_response *arm_resp = NULL;        
+        int found=0, size=0, rcode=-1;
+        quadlet_t old, new;
+        struct arm_request_response *arm_req_resp = NULL;
+
+        if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+                ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+                DBGMSG("arm_lock  called by node: %X "
+                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X", 
+                      nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+                      ext_tcode & 0xFF , be32_to_cpu(data));
+        } else {
+                DBGMSG("arm_lock  called by node: %X "
+                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X", 
+                      nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+                      ext_tcode & 0xFF , be32_to_cpu(data), be32_to_cpu(arg));
+        }
+        spin_lock(&host_info_lock);
+        hi = find_host_info(host); /* search address-entry */
+        if (hi != NULL) {
+                list_for_each(lh, &hi->file_info_list) {
+                        fi = list_entry(lh, struct file_info, list);
+                        entry = fi->addr_list.next;
+                        while (entry != &(fi->addr_list)) {
+                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                                if (((arm_addr->start) <= (addr)) && 
+                                        ((arm_addr->end) >= (addr+sizeof(*store)))) {
+                                        found = 1;
+                                        break;
+                                }
+                                entry = entry->next;
+                        }
+                        if (found) {
+                                break;
+                        }
+                }
+        }
+        rcode = -1;
+        if (!found) {
+                printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
+                " -> rcode_address_error\n");
+                spin_unlock(&host_info_lock);
+                return (RCODE_ADDRESS_ERROR);
+        } else {
+                DBGMSG("arm_lock addr_entry FOUND");
+        }
+        if (rcode == -1) {
+                if (arm_addr->access_rights & ARM_LOCK) {
+                        if (!(arm_addr->client_transactions & ARM_LOCK)) {
+                                memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
+                                        sizeof(old));
+                                switch (ext_tcode) {
+                                        case (EXTCODE_MASK_SWAP):
+                                                new = data | (old & ~arg);
+                                                break;
+                                        case (EXTCODE_COMPARE_SWAP):
+                                                if (old == arg) {
+                                                        new = data;
+                                                } else {
+                                                        new = old;
+                                                }
+                                                break;
+                                        case (EXTCODE_FETCH_ADD):
+                                                new = cpu_to_be32(be32_to_cpu(data) + be32_to_cpu(old));
+                                                break;
+                                        case (EXTCODE_LITTLE_ADD):
+                                                new = cpu_to_le32(le32_to_cpu(data) + le32_to_cpu(old));
+                                                break;
+                                        case (EXTCODE_BOUNDED_ADD):
+                                                if (old != arg) {
+                                                        new = cpu_to_be32(be32_to_cpu(data) + 
+                                                                be32_to_cpu(old));
+                                                } else {
+                                                        new = old;
+                                                }
+                                                break;
+                                        case (EXTCODE_WRAP_ADD):
+                                                if (old != arg) {
+                                                        new = cpu_to_be32(be32_to_cpu(data) + 
+                                                                be32_to_cpu(old));
+                                                } else {
+                                                        new = data;
+                                                }
+                                                break;
+                                        default:
+                                                rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                                                printk(KERN_ERR "raw1394: arm_lock FAILED "
+                                                "ext_tcode not allowed -> rcode_type_error\n");
+                                                break;
+                                } /*switch*/
+                                if (rcode == -1) {
+                                        DBGMSG("arm_lock -> (rcode_complete)");
+                                        rcode = RCODE_COMPLETE;
+                                        memcpy (store, &old, sizeof(*store));
+                                        memcpy ((arm_addr->addr_space_buffer)+
+                                                (addr-(arm_addr->start)), 
+                                                &new, sizeof(*store));
+                                }
+                        }
+                } else {
+                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                        DBGMSG("arm_lock -> rcode_type_error (access denied)");
+                }
+        }
+        if (arm_addr->notification_options & ARM_LOCK) {
+                DBGMSG("arm_lock -> entering notification-section");
+                req = __alloc_pending_request(SLAB_ATOMIC);
+                if (!req) {
+                        DBGMSG("arm_lock -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
+                        3 * sizeof(*store) + 
+                        sizeof (struct arm_request_response);  /* maximum */
+                req->data = kmalloc(size, SLAB_ATOMIC);
+                if (!(req->data)) {
+                        free_pending_request(req);
+                        DBGMSG("arm_lock -> rcode_conflict_error");
+                        spin_unlock(&host_info_lock);
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                req->free_data=1;
+                arm_req_resp = (struct arm_request_response *) (req->data);
+                arm_req  = (struct arm_request *) ((byte_t *)(req->data) + 
+                        (sizeof (struct arm_request_response)));
+                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + 
+                        (sizeof(struct arm_request)));
+                arm_req->buffer = ((byte_t *)(arm_resp) + 
+                        (sizeof(struct arm_response)));
+                arm_resp->buffer = ((byte_t *)(arm_req->buffer) + 
+                        (2* sizeof(*store)));
+                if ((ext_tcode == EXTCODE_FETCH_ADD) || 
+                        (ext_tcode == EXTCODE_LITTLE_ADD)) {
+                        arm_req->buffer_length = sizeof(*store);
+                        memcpy (arm_req->buffer, &data, sizeof(*store));
+
+                } else {
+                        arm_req->buffer_length = 2 * sizeof(*store);
+                        memcpy (arm_req->buffer, &arg,  sizeof(*store));
+                        memcpy (((arm_req->buffer) + sizeof(*store)), 
+                                &data, sizeof(*store));
+                }
+                if (rcode == RCODE_COMPLETE) {
+                        arm_resp->buffer_length = sizeof(*store);
+                        memcpy (arm_resp->buffer, &old, sizeof(*store));
+                } else {
+                        arm_resp->buffer = NULL;
+                        arm_resp->buffer_length = 0;
+                }
+                req->file_info = fi;
+                req->req.type = RAW1394_REQ_ARM;
+                req->req.generation = get_hpsb_generation(host);
+                req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | 
+                        (ARM_LOCK & 0xFF));
+                req->req.tag  = arm_addr->arm_tag;
+                req->req.recvb = arm_addr->recvb;
+                req->req.length = size;
+                arm_req->generation = req->req.generation;
+                arm_req->extended_transaction_code = ext_tcode;
+                arm_req->destination_offset = addr;
+                arm_req->source_nodeid = nodeid;
+                arm_req->destination_nodeid = host->node_id;
+                arm_req->tlabel = (flags >> 10) & 0x3f;
+                arm_req->tcode = (flags >> 4) & 0x0f;
+                arm_resp->response_code = rcode;
+                arm_req_resp->request  = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response));
+                arm_req_resp->response = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request));
+                arm_req->buffer = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request) +
+                        sizeof (struct arm_response));
+                arm_resp->buffer = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request) +
+                        sizeof (struct arm_response) +
+                        2* sizeof (*store));
+                queue_complete_req(req);
+        }
+        spin_unlock(&host_info_lock);
+        return(rcode);
+}
+
+static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
+               u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
+{
+        struct pending_request *req;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi = NULL;
+        struct list_head *entry;
+        struct arm_addr  *arm_addr = NULL;
+        struct arm_request  *arm_req = NULL;
+        struct arm_response *arm_resp = NULL;
+        int found=0, size=0, rcode=-1;
+        octlet_t old, new;
+        struct arm_request_response *arm_req_resp = NULL;
+
+        if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+                ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+                DBGMSG("arm_lock64 called by node: %X "
+                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
+                      nodeid, (u16) ((addr >>32) & 0xFFFF),
+                      (u32) (addr & 0xFFFFFFFF), 
+                      ext_tcode & 0xFF , 
+                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), 
+                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
+        } else {
+                DBGMSG("arm_lock64 called by node: %X "
+                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
+                      "%8.8X %8.8X ",
+                      nodeid, (u16) ((addr >>32) & 0xFFFF),
+                      (u32) (addr & 0xFFFFFFFF), 
+                      ext_tcode & 0xFF , 
+                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), 
+                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
+                      (u32) ((be64_to_cpu(arg)  >> 32) & 0xFFFFFFFF), 
+                      (u32) (be64_to_cpu(arg)  & 0xFFFFFFFF));
+        }
+        spin_lock(&host_info_lock);
+        hi = find_host_info(host); /* search addressentry in file_info's for host */
+        if (hi != NULL) {
+                list_for_each(lh, &hi->file_info_list) {
+                        fi = list_entry(lh, struct file_info, list);
+                        entry = fi->addr_list.next;
+                        while (entry != &(fi->addr_list)) {
+                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                                if (((arm_addr->start) <= (addr)) && 
+                                        ((arm_addr->end) >= (addr+sizeof(*store)))) {
+                                        found = 1;
+                                        break;
+                                }
+                                entry = entry->next;
+                        }
+                        if (found) {
+                                break;
+                        }
+                }
+        }
+        rcode = -1;
+        if (!found) {
+                printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found"
+                " -> rcode_address_error\n");
+                spin_unlock(&host_info_lock);
+                return (RCODE_ADDRESS_ERROR);
+        } else {
+                DBGMSG("arm_lock64 addr_entry FOUND");
+        }
+        if (rcode == -1) {
+                if (arm_addr->access_rights & ARM_LOCK) {
+                        if (!(arm_addr->client_transactions & ARM_LOCK)) {
+                                memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
+                                        sizeof(old));
+                                switch (ext_tcode) {
+                                        case (EXTCODE_MASK_SWAP):
+                                                new = data | (old & ~arg);
+                                                break;
+                                        case (EXTCODE_COMPARE_SWAP):
+                                                if (old == arg) {
+                                                        new = data;
+                                                } else {
+                                                        new = old;
+                                                }
+                                                break;
+                                        case (EXTCODE_FETCH_ADD):
+                                                new = cpu_to_be64(be64_to_cpu(data) + be64_to_cpu(old));
+                                                break;
+                                        case (EXTCODE_LITTLE_ADD):
+                                                new = cpu_to_le64(le64_to_cpu(data) + le64_to_cpu(old));
+                                                break;
+                                        case (EXTCODE_BOUNDED_ADD):
+                                                if (old != arg) {
+                                                        new = cpu_to_be64(be64_to_cpu(data) + 
+                                                                be64_to_cpu(old));
+                                                } else {
+                                                        new = old;
+                                                }
+                                                break;
+                                        case (EXTCODE_WRAP_ADD):
+                                                if (old != arg) {
+                                                        new = cpu_to_be64(be64_to_cpu(data) + 
+                                                                be64_to_cpu(old));
+                                                } else {
+                                                        new = data;
+                                                }
+                                                break;
+                                        default:
+                                                printk(KERN_ERR "raw1394: arm_lock64 FAILED "
+                                                "ext_tcode not allowed -> rcode_type_error\n");
+                                                rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                                                break;
+                                } /*switch*/
+                                if (rcode == -1) {
+                                        DBGMSG("arm_lock64 -> (rcode_complete)");
+                                        rcode = RCODE_COMPLETE;
+                                        memcpy (store, &old, sizeof(*store));
+                                        memcpy ((arm_addr->addr_space_buffer)+
+                                                (addr-(arm_addr->start)), 
+                                                &new, sizeof(*store));
+                                } 
+                        }
+                } else {
+                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
+                        DBGMSG("arm_lock64 -> rcode_type_error (access denied)");
+                }
+        }
+        if (arm_addr->notification_options & ARM_LOCK) {
+                DBGMSG("arm_lock64 -> entering notification-section");
+                req = __alloc_pending_request(SLAB_ATOMIC);
+                if (!req) {
+                        spin_unlock(&host_info_lock);
+                        DBGMSG("arm_lock64 -> rcode_conflict_error");
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
+                        3 * sizeof(*store) +
+                        sizeof (struct arm_request_response); /* maximum */
+                req->data = kmalloc(size, SLAB_ATOMIC);
+                if (!(req->data)) {
+                        free_pending_request(req);
+                        spin_unlock(&host_info_lock);
+                        DBGMSG("arm_lock64 -> rcode_conflict_error");
+                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. 
+                                                        The request may be retried */
+                }
+                req->free_data=1;
+                arm_req_resp = (struct arm_request_response *) (req->data);
+                arm_req  = (struct arm_request *) ((byte_t *)(req->data) + 
+                        (sizeof (struct arm_request_response)));
+                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + 
+                        (sizeof(struct arm_request)));
+                arm_req->buffer = ((byte_t *)(arm_resp) + 
+                        (sizeof(struct arm_response)));
+                arm_resp->buffer = ((byte_t *)(arm_req->buffer) + 
+                        (2* sizeof(*store)));
+                if ((ext_tcode == EXTCODE_FETCH_ADD) || 
+                        (ext_tcode == EXTCODE_LITTLE_ADD)) {
+                        arm_req->buffer_length = sizeof(*store);
+                        memcpy (arm_req->buffer, &data, sizeof(*store));
+
+                } else {
+                        arm_req->buffer_length = 2 * sizeof(*store);
+                        memcpy (arm_req->buffer, &arg,  sizeof(*store));
+                        memcpy (((arm_req->buffer) + sizeof(*store)), 
+                                &data, sizeof(*store));
+                }
+                if (rcode == RCODE_COMPLETE) {
+                        arm_resp->buffer_length = sizeof(*store);
+                        memcpy (arm_resp->buffer, &old, sizeof(*store));
+                } else {
+                        arm_resp->buffer = NULL;
+                        arm_resp->buffer_length = 0;
+                }
+                req->file_info = fi;
+                req->req.type = RAW1394_REQ_ARM;
+                req->req.generation = get_hpsb_generation(host);
+                req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | 
+                        (ARM_LOCK & 0xFF));
+                req->req.tag  = arm_addr->arm_tag;
+                req->req.recvb = arm_addr->recvb;
+                req->req.length = size;
+                arm_req->generation = req->req.generation;
+                arm_req->extended_transaction_code = ext_tcode;
+                arm_req->destination_offset = addr;
+                arm_req->source_nodeid = nodeid;
+                arm_req->destination_nodeid = host->node_id;
+                arm_req->tlabel = (flags >> 10) & 0x3f;
+                arm_req->tcode = (flags >> 4) & 0x0f;
+                arm_resp->response_code = rcode;
+                arm_req_resp->request  = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response));
+                arm_req_resp->response = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request));
+                arm_req->buffer = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request) +
+                        sizeof (struct arm_response));
+                arm_resp->buffer = int2ptr((arm_addr->recvb) + 
+                        sizeof (struct arm_request_response) +
+                        sizeof (struct arm_request) +
+                        sizeof (struct arm_response) +
+                        2* sizeof (*store));
+                queue_complete_req(req);
+        }
+        spin_unlock(&host_info_lock);
+        return(rcode);
+}
+
+static int arm_register(struct file_info *fi, struct pending_request *req)
+{
+        int retval;
+        struct arm_addr *addr;
+        struct list_head *lh, *lh_1, *lh_2;
+        struct host_info *hi;
+        struct file_info *fi_hlp = NULL;
+        struct list_head *entry;
+        struct arm_addr  *arm_addr = NULL;
+        int same_host, another_host;
+        unsigned long flags;
+
+        DBGMSG("arm_register called "
+              "addr(Offset): %8.8x %8.8x length: %u "
+              "rights: %2.2X notify: %2.2X "
+              "max_blk_len: %4.4X",
+              (u32) ((req->req.address >>32) & 0xFFFF),
+              (u32) (req->req.address & 0xFFFFFFFF),
+              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)) {
+                req->req.length = 0;
+                return (-EINVAL);
+        }
+        /* addr-list-entry for fileinfo */
+        addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL); 
+        if (!addr) {
+                req->req.length = 0;
+                return (-ENOMEM);
+        } 
+        /* allocation of addr_space_buffer */
+        addr->addr_space_buffer = (u8 *)kmalloc(req->req.length,SLAB_KERNEL);
+        if (!(addr->addr_space_buffer)) {
+                kfree(addr);
+                req->req.length = 0;
+                return (-ENOMEM);
+        }
+        /* initialization of addr_space_buffer */
+        if ((req->req.sendb)== (unsigned long)NULL) {
+                /* init: set 0 */
+                memset(addr->addr_space_buffer, 0,req->req.length);
+        } else {
+                /* init: user -> kernel */
+                if (copy_from_user(addr->addr_space_buffer,int2ptr(req->req.sendb),
+                        req->req.length)) {
+                        kfree(addr->addr_space_buffer);
+                        kfree(addr);
+                        return (-EFAULT);
+                }
+        }
+        INIT_LIST_HEAD(&addr->addr_list);
+        addr->arm_tag   = req->req.tag;
+        addr->start     = req->req.address;
+        addr->end       = req->req.address + req->req.length;
+        addr->access_rights = (u8) (req->req.misc & 0x0F);
+        addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
+        addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
+        addr->access_rights |= addr->client_transactions;
+        addr->notification_options |= addr->client_transactions;
+        addr->recvb     = req->req.recvb;
+        addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
+        spin_lock_irqsave(&host_info_lock, flags);
+        hi = find_host_info(fi->host);
+        same_host = 0;
+        another_host = 0;
+        /* same host with address-entry containing same addressrange ? */
+        list_for_each(lh, &hi->file_info_list) {
+                fi_hlp = list_entry(lh, struct file_info, list);
+                entry = fi_hlp->addr_list.next;
+                while (entry != &(fi_hlp->addr_list)) {
+                        arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                        if ( (arm_addr->start == addr->start) && 
+                                (arm_addr->end == addr->end)) {
+                                DBGMSG("same host ownes same "
+                                        "addressrange -> EALREADY");
+                                same_host = 1;
+                                break;
+                        }
+                        entry = entry->next;
+                }
+                if (same_host) {
+                        break;
+                }
+        }
+        if (same_host) {
+                /* addressrange occupied by same host */
+                kfree(addr->addr_space_buffer);
+                kfree(addr);
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return (-EALREADY);
+        }
+        /* another host with valid address-entry containing same addressrange */
+        list_for_each(lh_1, &host_info_list) {
+                hi = list_entry(lh_1, struct host_info, list);
+                if (hi->host != fi->host) {
+                        list_for_each(lh_2, &hi->file_info_list) {
+                                fi_hlp = list_entry(lh_2, struct file_info, list);
+                                entry = fi_hlp->addr_list.next;
+                                while (entry != &(fi_hlp->addr_list)) {
+                                        arm_addr = list_entry(entry, struct arm_addr, addr_list);
+                                        if ( (arm_addr->start == addr->start) && 
+                                                (arm_addr->end == addr->end)) {
+                                                DBGMSG("another host ownes same "
+                                                "addressrange");
+                                                another_host = 1;
+                                                break;
+                                        }
+                                        entry = entry->next;
+                                }
+                                if (another_host) {
+                                        break;
+                                }
+                        }
+                }
+        }
+        if (another_host) {
+                DBGMSG("another hosts entry is valid -> SUCCESS");
+                if (copy_to_user(int2ptr(req->req.recvb),
+                        int2ptr(&addr->start),sizeof(u64))) {
+                        printk(KERN_ERR "raw1394: arm_register failed "
+                              " address-range-entry is invalid -> EFAULT !!!\n");
+                        kfree(addr->addr_space_buffer);
+                        kfree(addr);
+                        spin_unlock_irqrestore(&host_info_lock, flags);
+                        return (-EFAULT);
+                }
+                free_pending_request(req); /* immediate success or fail */
+                /* INSERT ENTRY */
+                list_add_tail(&addr->addr_list, &fi->addr_list);
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return sizeof(struct raw1394_request);
+        }
+        retval = hpsb_register_addrspace(hl_handle, &arm_ops, req->req.address,
+                req->req.address + req->req.length);
+        if (retval) {
+               /* INSERT ENTRY */
+               list_add_tail(&addr->addr_list, &fi->addr_list);
+        } else {
+                DBGMSG("arm_register failed errno: %d \n",retval);
+                kfree(addr->addr_space_buffer);
+                kfree(addr);
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return (-EALREADY); 
+        }
+        spin_unlock_irqrestore(&host_info_lock, flags);
+        free_pending_request(req); /* immediate success or fail */
+        return sizeof(struct raw1394_request);
+}
+
+static int arm_unregister(struct file_info *fi, struct pending_request *req)
+{
+        int found  = 0;
+        int retval = 0;
+        struct list_head *entry;
+        struct arm_addr  *addr = NULL;
+        struct list_head *lh_1, *lh_2;
+        struct host_info *hi;
+        struct file_info *fi_hlp = NULL;
+        struct arm_addr  *arm_addr = NULL;
+        int another_host;
+        unsigned long flags;
+
+        DBGMSG("arm_Unregister called addr(Offset): "
+              "%8.8x %8.8x",
+              (u32) ((req->req.address >>32) & 0xFFFF),
+              (u32) (req->req.address & 0xFFFFFFFF));
+        spin_lock_irqsave(&host_info_lock, flags);
+        /* get addr */
+        entry = fi->addr_list.next;
+        while (entry != &(fi->addr_list)) {
+                addr = list_entry(entry, struct arm_addr, addr_list);
+                if (addr->start == req->req.address) {
+                        found = 1;
+                        break;
+                }
+                entry = entry->next;
+        }
+        if (!found) {
+                DBGMSG("arm_Unregister addr not found");
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return (-EINVAL);
+        }
+        DBGMSG("arm_Unregister addr found");
+        another_host = 0;
+        /* another host with valid address-entry containing 
+           same addressrange */
+        list_for_each(lh_1, &host_info_list) {
+                hi = list_entry(lh_1, struct host_info, list);
+                if (hi->host != fi->host) {
+                        list_for_each(lh_2, &hi->file_info_list) {
+                                fi_hlp = list_entry(lh_2, struct file_info, list);
+                                entry = fi_hlp->addr_list.next;
+                                while (entry != &(fi_hlp->addr_list)) {
+                                        arm_addr = list_entry(entry, 
+                                                struct arm_addr, addr_list);
+                                        if (arm_addr->start == 
+                                                addr->start) {
+                                                DBGMSG("another host ownes "
+                                                "same addressrange");
+                                                another_host = 1;
+                                                break;
+                                        }
+                                        entry = entry->next;
+                                }
+                                if (another_host) {
+                                        break;
+                                }
+                        }
+                }
+        }
+        if (another_host) {
+                DBGMSG("delete entry from list -> success");
+                list_del(&addr->addr_list);
+                kfree(addr->addr_space_buffer);
+                kfree(addr);
+                free_pending_request(req); /* immediate success or fail */
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return sizeof(struct raw1394_request);
+        } 
+        retval = hpsb_unregister_addrspace(hl_handle, addr->start);
+        if (!retval) {
+                printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
+                spin_unlock_irqrestore(&host_info_lock, flags);
+                return (-EINVAL);
+        }
+        DBGMSG("delete entry from list -> success");
+        list_del(&addr->addr_list);
+        spin_unlock_irqrestore(&host_info_lock, flags);
+        kfree(addr->addr_space_buffer);
+        kfree(addr);
+        free_pending_request(req); /* immediate success or fail */
+        return sizeof(struct raw1394_request);
+}
+
+static int reset_notification(struct file_info *fi, struct pending_request *req)
+{
+        DBGMSG("reset_notification called - switch %s ",
+                (req->req.misc == RAW1394_NOTIFY_OFF)?"OFF":"ON");
+        if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
+                (req->req.misc == RAW1394_NOTIFY_ON)) {
+                fi->notification=(u8)req->req.misc;
+                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+                return sizeof(struct raw1394_request);
+        } 
+        /* error EINVAL (22) invalid argument */
+        return (-EINVAL);
+}
+
+static int write_phypacket(struct file_info *fi, struct pending_request *req)
+{
+        struct hpsb_packet *packet = NULL;
+        int retval=0;
+        quadlet_t data;
+
+        data = be32_to_cpu((u32)req->req.sendb);
+        DBGMSG("write_phypacket called - quadlet 0x%8.8x ",data);
+        packet = hpsb_make_phypacket (fi->host, data);
+        if (!packet) return -ENOMEM;
+        req->req.length=0;
+        req->packet=packet;
+        req->tq.data=req;
+        hpsb_add_packet_complete_task(packet, &req->tq);
+        spin_lock_irq(&fi->reqlists_lock);
+        list_add_tail(&req->list, &fi->req_pending);
+        spin_unlock_irq(&fi->reqlists_lock);
+        packet->generation = req->req.generation;
+        retval = hpsb_send_packet(packet);
+        DBGMSG("write_phypacket send_packet called => retval: %d ",
+                retval);
+        if (! retval) {
+                req->req.error = RAW1394_ERROR_SEND_ERROR;
+                req->req.length = 0;
+                queue_complete_req(req);
+        }
+        return sizeof(struct raw1394_request);
+}
+
+static int get_config_rom(struct file_info *fi, struct pending_request *req)
+{
+        size_t return_size;
+        unsigned char rom_version;
+        int ret=sizeof(struct raw1394_request);
+        quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+        int status;
+        if (!data) return -ENOMEM;
+        status = hpsb_get_config_rom(fi->host, data, 
+                req->req.length, &return_size, &rom_version);
+        if (copy_to_user(int2ptr(req->req.recvb), data, 
+                req->req.length))
+                ret = -EFAULT;
+        if (copy_to_user(int2ptr(req->req.tag), &return_size, 
+                sizeof(return_size)))
+                ret = -EFAULT;
+        if (copy_to_user(int2ptr(req->req.address), &rom_version, 
+                sizeof(rom_version)))
+                ret = -EFAULT;
+        if (copy_to_user(int2ptr(req->req.sendb), &status, 
+                sizeof(status)))
+                ret = -EFAULT;
+        kfree(data);
+        if (ret >= 0) {
+                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+        }
+        return ret;
+}
+
+static int update_config_rom(struct file_info *fi, struct pending_request *req)
+{
+        int ret=sizeof(struct raw1394_request);
+        quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+        if (!data) return -ENOMEM;
+        if (copy_from_user(data,int2ptr(req->req.sendb), 
+                req->req.length)) {
+                ret= -EFAULT;
+        } else {
+                int status = hpsb_update_config_rom(fi->host, 
+                        data, req->req.length, 
+                        (unsigned char) req->req.misc);
+                if (copy_to_user(int2ptr(req->req.recvb), 
+                        &status, sizeof(status)))
+                        ret = -ENOMEM;
+        }
+        kfree(data);
+        if (ret >= 0) {
+                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+        }
+        return ret;
+}
+
+static int state_connected(struct file_info *fi, struct pending_request *req)
+{
+        int node = req->req.address >> 48;
+
+        req->req.error = RAW1394_ERROR_NONE;
+
         switch (req->req.type) {
+
+        case RAW1394_REQ_ECHO:
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+
+        case RAW1394_REQ_ISO_SEND:
+                return handle_iso_send(fi, req, node);
+
+        case RAW1394_REQ_ARM_REGISTER:
+                return arm_register(fi, req);
+
+        case RAW1394_REQ_ARM_UNREGISTER:
+                return arm_unregister(fi, req);
+
+        case RAW1394_REQ_RESET_NOTIFY:
+                return reset_notification(fi, req);
+
         case RAW1394_REQ_ISO_LISTEN:
                 handle_iso_listen(fi, req);
                 return sizeof(struct raw1394_request);
@@ -831,21 +1908,49 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
                 return sizeof(struct raw1394_request);
 
         case RAW1394_REQ_RESET_BUS:
-                hpsb_reset_bus(fi->host, LONG_RESET);
+                if (req->req.misc == RAW1394_LONG_RESET) {
+                        DBGMSG("busreset called (type: LONG)");
+                        hpsb_reset_bus(fi->host, LONG_RESET);
+                        free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+                        return sizeof(struct raw1394_request);
+                }
+                if (req->req.misc == RAW1394_SHORT_RESET) {
+                        DBGMSG("busreset called (type: SHORT)");
+                        hpsb_reset_bus(fi->host, SHORT_RESET);
+                        free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+                        return sizeof(struct raw1394_request);
+                }
+                /* error EINVAL (22) invalid argument */
+                return (-EINVAL);
+        case RAW1394_REQ_GET_ROM:
+                return get_config_rom(fi, req);
+
+        case RAW1394_REQ_UPDATE_ROM:
+                return update_config_rom(fi, req);
+        }
+
+        if (req->req.generation != get_hpsb_generation(fi->host)) {
+                req->req.error = RAW1394_ERROR_GENERATION;
+                req->req.generation = get_hpsb_generation(fi->host);
+                req->req.length = 0;
+                queue_complete_req(req);
                 return sizeof(struct raw1394_request);
         }
 
+        switch (req->req.type) {
+        case RAW1394_REQ_PHYPACKET:
+                return write_phypacket(fi, req);
+        case RAW1394_REQ_ASYNC_SEND:
+                return handle_async_send(fi, req);
+        }
+
         if (req->req.length == 0) {
                 req->req.error = RAW1394_ERROR_INVALID_ARG;
                 queue_complete_req(req);
                 return sizeof(struct raw1394_request);
         }
 
-        if (fi->host->node_id == node) {
-                return handle_local_request(fi, req, node);
-        }
-
-        return handle_remote_request(fi, req, node);
+        return handle_async_request(fi, req, node);
 }
 
 
@@ -921,6 +2026,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
                 return -ENOMEM;
         
         memset(fi, 0, sizeof(struct file_info));
+        fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
 
         INIT_LIST_HEAD(&fi->list);
         fi->state = opened;
@@ -929,6 +2035,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
         sema_init(&fi->complete_sem, 0);
         spin_lock_init(&fi->reqlists_lock);
         init_waitqueue_head(&fi->poll_wait_complete);
+        INIT_LIST_HEAD(&fi->addr_list);
 
         file->private_data = fi;
 
@@ -940,7 +2047,15 @@ static int raw1394_release(struct inode *inode, struct file *file)
         struct file_info *fi = file->private_data;
         struct list_head *lh;
         struct pending_request *req;
-        int done = 0, i;
+        int done = 0, i, fail = 0;
+        int retval = 0;
+        struct list_head *entry;
+        struct arm_addr  *addr = NULL;
+        struct list_head *lh_1, *lh_2;
+        struct host_info *hi;
+        struct file_info *fi_hlp = NULL;
+        struct arm_addr  *arm_addr = NULL;
+        int another_host;
 
         for (i = 0; i < 64; i++) {
                 if (fi->listen_channels & (1ULL << i)) {
@@ -948,9 +2063,63 @@ static int raw1394_release(struct inode *inode, struct file *file)
                 }
         }
 
-        spin_lock(&host_info_lock);
+        spin_lock_irq(&host_info_lock);
         fi->listen_channels = 0;
-        spin_unlock(&host_info_lock);
+        spin_unlock_irq(&host_info_lock);
+
+        fail = 0;
+        /* set address-entries invalid */
+        spin_lock_irq(&host_info_lock);
+
+        while (!list_empty(&fi->addr_list)) {
+                another_host = 0;
+                lh = fi->addr_list.next;
+                addr = list_entry(lh, struct arm_addr, addr_list);
+                /* another host with valid address-entry containing 
+                   same addressrange? */
+                list_for_each(lh_1, &host_info_list) {
+                        hi = list_entry(lh_1, struct host_info, list);
+                        if (hi->host != fi->host) {
+                                list_for_each(lh_2, &hi->file_info_list) {
+                                        fi_hlp = list_entry(lh_2, struct file_info, list);
+                                        entry = fi_hlp->addr_list.next;
+                                        while (entry != &(fi_hlp->addr_list)) {
+                                                arm_addr = list_entry(entry, 
+                                                        struct arm_addr, addr_list);
+                                                if (arm_addr->start == 
+                                                        addr->start) {
+                                                        DBGMSG("raw1394_release: "
+                                                        "another host ownes "
+                                                        "same addressrange");
+                                                        another_host = 1;
+                                                        break;
+                                                }
+                                                entry = entry->next;
+                                        }
+                                        if (another_host) {
+                                                break;
+                                        }
+                                }
+                        }
+                }
+                if (!another_host) {
+                        DBGMSG("raw1394_release: call hpsb_arm_unregister");
+                        retval = hpsb_unregister_addrspace(hl_handle, addr->start);
+                        if (!retval) {
+                                ++fail;
+                                printk(KERN_ERR "raw1394_release arm_Unregister failed\n");
+                        }
+                }
+                DBGMSG("raw1394_release: delete addr_entry from list");
+                list_del(&addr->addr_list);
+                kfree(addr->addr_space_buffer);
+                kfree(addr);
+        } /* while */
+        spin_unlock_irq(&host_info_lock);
+        if (fail > 0) {
+                printk(KERN_ERR "raw1394: during addr_list-release "
+                        "error(s) occured \n");
+        }
 
         while (!done) {
                 spin_lock_irq(&fi->reqlists_lock);
@@ -1009,28 +2178,28 @@ static int __init init_raw1394(void)
                 return -ENOMEM;
         }
 
-       devfs_handle = devfs_register(NULL,
-                                     RAW1394_DEVICE_NAME, DEVFS_FL_NONE,
+        devfs_handle = devfs_register(NULL,
+                                      RAW1394_DEVICE_NAME, DEVFS_FL_NONE,
                                       IEEE1394_MAJOR,
-                                     IEEE1394_MINOR_BLOCK_RAW1394 * 16,
+                                      IEEE1394_MINOR_BLOCK_RAW1394 * 16,
                                       S_IFCHR | S_IRUSR | S_IWUSR, &file_ops,
                                       NULL);
 
         if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394,
-                                     THIS_MODULE, &file_ops)) {
+                                      THIS_MODULE, &file_ops)) {
                 HPSB_ERR("raw1394 failed to register minor device block");
-               devfs_unregister(devfs_handle);
-               hpsb_unregister_highlevel(hl_handle);
+                devfs_unregister(devfs_handle);
+                hpsb_unregister_highlevel(hl_handle);
                 return -EBUSY;
         }
-       printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME);
+        printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME);
         return 0;
 }
 
 static void __exit cleanup_raw1394(void)
 {
         ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394);
-       devfs_unregister(devfs_handle);
+        devfs_unregister(devfs_handle);
         hpsb_unregister_highlevel(hl_handle);
 }
 
index 98c6298233ae6018a2952a7b0e06748883ad3ff5..c9e72a56e47563acb384f5a4c4f9019207ba0bf0 100644 (file)
 #define RAW1394_REQ_SET_CARD      3
 
 /* state: connected */
-#define RAW1394_REQ_ASYNC_READ    100
-#define RAW1394_REQ_ASYNC_WRITE   101
-#define RAW1394_REQ_LOCK          102
-#define RAW1394_REQ_LOCK64        103
-#define RAW1394_REQ_ISO_SEND      104
+#define RAW1394_REQ_ASYNC_READ      100
+#define RAW1394_REQ_ASYNC_WRITE     101
+#define RAW1394_REQ_LOCK            102
+#define RAW1394_REQ_LOCK64          103
+#define RAW1394_REQ_ISO_SEND        104
+#define RAW1394_REQ_ASYNC_SEND      105
 
-#define RAW1394_REQ_ISO_LISTEN    200
-#define RAW1394_REQ_FCP_LISTEN    201
-#define RAW1394_REQ_RESET_BUS     202
+#define RAW1394_REQ_ISO_LISTEN      200
+#define RAW1394_REQ_FCP_LISTEN      201
+#define RAW1394_REQ_RESET_BUS       202
+#define RAW1394_REQ_GET_ROM         203
+#define RAW1394_REQ_UPDATE_ROM      204
+#define RAW1394_REQ_ECHO            205
+
+#define RAW1394_REQ_ARM_REGISTER    300
+#define RAW1394_REQ_ARM_UNREGISTER  301
+
+#define RAW1394_REQ_RESET_NOTIFY    400
+
+#define RAW1394_REQ_PHYPACKET       500
 
 /* kernel to user */
 #define RAW1394_REQ_BUS_RESET     10000
 #define RAW1394_REQ_ISO_RECEIVE   10001
 #define RAW1394_REQ_FCP_REQUEST   10002
+#define RAW1394_REQ_ARM           10003
 
 /* error codes */
 #define RAW1394_ERROR_NONE        0
 #define RAW1394_ERROR_ABORTED     (-1101)
 #define RAW1394_ERROR_TIMEOUT     (-1102)
 
+/* arm_codes */
+#define ARM_READ   1
+#define ARM_WRITE  2
+#define ARM_LOCK   4
+
+#define RAW1394_LONG_RESET  0
+#define RAW1394_SHORT_RESET 1
+
+/* busresetnotify ... */
+#define RAW1394_NOTIFY_OFF 0
+#define RAW1394_NOTIFY_ON  1
 
 #include <asm/types.h>
 
@@ -69,6 +92,29 @@ struct raw1394_khost_list {
         __u8 name[32];
 };
 
+typedef struct arm_request {
+        nodeid_t        destination_nodeid;
+        nodeid_t        source_nodeid;
+        nodeaddr_t      destination_offset;
+        u8              tlabel;
+        u8              tcode;
+        u_int8_t        extended_transaction_code;
+        u_int32_t       generation;
+        arm_length_t    buffer_length;
+        byte_t          *buffer;
+} *arm_request_t;
+
+typedef struct arm_response {
+        int             response_code;
+        arm_length_t    buffer_length;
+        byte_t          *buffer;
+} *arm_response_t;
+
+typedef struct arm_request_response {
+        struct arm_request  *request;
+        struct arm_response *response;
+} *arm_request_response_t;
+
 #ifdef __KERNEL__
 
 struct iso_block_store {
@@ -91,18 +137,34 @@ struct file_info {
         spinlock_t reqlists_lock;
         wait_queue_head_t poll_wait_complete;
 
+        struct list_head addr_list;           
+
         u8 *fcp_buffer;
 
         u64 listen_channels;
         quadlet_t *iso_buffer;
         size_t iso_buffer_length;
+
+        u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
+};
+
+struct arm_addr {
+        struct list_head addr_list; /* file_info list */
+        u64    start, end;
+        u64    arm_tag;
+        u8     access_rights;
+        u8     notification_options;
+        u8     client_transactions;
+        u64    recvb;
+        u16    rec_length;
+        u8     *addr_space_buffer; /* accessed by read/write/lock */
 };
 
 struct pending_request {
         struct list_head list;
         struct file_info *file_info;
         struct hpsb_packet *packet;
-        struct tq_struct tq;
+        struct hpsb_queue_struct tq;
         struct iso_block_store *ibs;
         quadlet_t *data;
         int free_data;
index f50323e976dbe1322c5e77addad36dc17c7af558..d8ff4fd44d55a25353d8c9115656a5d08230658d 100644 (file)
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-       "$Rev: 584 $ James Goodwin <jamesg@filanet.com>";
+       "$Rev: 601 $ James Goodwin <jamesg@filanet.com>";
 
 /*
  * Module load parameter definitions
@@ -421,8 +421,9 @@ static int sbp2_max_cmds_per_lun = SBP2SCSI_MAX_CMDS_PER_LUN;
  * talking to a single sbp2 device at the same time (filesystem coherency,
  * etc.). If you're running an sbp2 device that supports multiple logins,
  * and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts, then set sbp2_exclusive_login to
- * zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four
+ * filesystem supporting multiple hosts (one such filesystem is OpenGFS,
+ * see opengfs.sourceforge.net for more info), then set sbp2_exclusive_login
+ * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four
  * concurrent logins.
  */
 MODULE_PARM(sbp2_exclusive_login,"i");
@@ -800,8 +801,9 @@ sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
                 * Set up a task queue completion routine, which returns
                 * the packet to the free list and releases the tlabel.
                 */
-               request_packet->tq.routine = (void (*)(void*))sbp2util_free_request_packet;
-               request_packet->tq.data = request_packet;
+               HPSB_PREPARE_WORK(&request_packet->tq,
+                                 (void (*)(void*))sbp2util_free_request_packet,
+                                 request_packet);
                request_packet->hi_context = hi;
                hpsb_add_packet_complete_task(packet, &request_packet->tq);
 
@@ -1007,13 +1009,8 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
                                         command->dma_size, command->dma_dir);
                        SBP2_DMA_FREE("single bulk");
                } else if (command->dma_type == CMD_DMA_PAGE) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13)
-                       pci_unmap_single(hi->host->pdev, command->cmd_dma,
-                                        command->dma_size, command->dma_dir);
-#else
                        pci_unmap_page(hi->host->pdev, command->cmd_dma,
                                       command->dma_size, command->dma_dir);
-#endif /* Linux version < 2.4.13 */
                        SBP2_DMA_FREE("single page");
                } /* XXX: Check for CMD_DMA_NONE bug */
                command->dma_type = CMD_DMA_NONE;
@@ -2146,17 +2143,11 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
                        command->dma_dir = dma_dir;
                        command->dma_size = sgpnt[0].length;
                        command->dma_type = CMD_DMA_PAGE;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13)
-                       command->cmd_dma = pci_map_single (hi->host->pdev, sgpnt[0].address,
-                                                          command->dma_size,
-                                                          command->dma_dir);
-#else
                        command->cmd_dma = pci_map_page(hi->host->pdev,
                                                        sgpnt[0].page,
                                                        sgpnt[0].offset,
                                                        command->dma_size,
                                                        command->dma_dir);
-#endif /* Linux version < 2.4.13 */
                        SBP2_DMA_ALLOC("single page scatter element");
 
                        command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
@@ -2702,7 +2693,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
  * This function deals with status writes from the SBP-2 device
  */
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
-                                   quadlet_t *data, u64 addr, unsigned int length)
+                                   quadlet_t *data, u64 addr, unsigned int length, u16 fl)
 {
        struct sbp2scsi_host_info *hi = NULL;
        struct scsi_id_instance_data *scsi_id = NULL;
@@ -3161,7 +3152,6 @@ static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int ge
        heads = 64;
        sectors = 32;
        cylinders = (int)disk->capacity / (heads * sectors);
-       
 
        if (cylinders > 1024) {
                heads = 255;
index 59447232547d495cd7af6316bcfb2e0fd9d5d995..7d8178bc786fe87fb65fa470b14268acb36fc460 100644 (file)
@@ -324,7 +324,7 @@ struct sbp2_request_packet {
 
        struct list_head list;
        struct hpsb_packet *packet;
-       struct tq_struct tq;
+       struct hpsb_queue_struct tq;
        void *hi_context;
 
 };
@@ -510,9 +510,9 @@ static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
 
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
 static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
-                                     u64 addr, unsigned int length);
+                                     u64 addr, unsigned int length, u16 flags);
 static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                    u64 addr, unsigned int length);
+                                    u64 addr, unsigned int length, u16 flags);
 #endif
 
 /*
@@ -522,7 +522,7 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
 static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); 
 static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); 
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
-                                   quadlet_t *data, u64 addr, unsigned int length);
+                                   quadlet_t *data, u64 addr, unsigned int length, u16 flags);
 static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 flags);
 static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, 
                                   struct scsi_id_instance_data *scsi_id,
index 24b18e4649520cf166ab956c0cc801b6aefcae4c..dc8a50b6741ae980b73cb4782886a1b76ffcc7e1 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
 #include <linux/delay.h>
 #include <linux/devfs_fs_kernel.h>
 
@@ -1455,12 +1454,7 @@ static int __init video1394_init_module (void)
                return -EIO;
        }
        
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-       devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME,
-                       strlen(VIDEO1394_DRIVER_NAME), NULL);
-#else
        devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
-#endif
 
        hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
        if (hl_handle == NULL) {