]> git.hungrycats.org Git - linux/commitdiff
[PATCH] IEEE1394 updates
authorBen Collins <bcollins@debian.org>
Tue, 4 Mar 2003 02:55:45 +0000 (18:55 -0800)
committerBen Collins <bcollins@debian.org>
Tue, 4 Mar 2003 02:55:45 +0000 (18:55 -0800)
- Add ioctl32 compat function registration for video1394, dv1394 and
  amdtp.
- Convert SBP-2 driver to new SCSI hotplug host/device interfaces.
- Initial Async ISO (GASP) support.

17 files changed:
drivers/ieee1394/amdtp.c
drivers/ieee1394/dma.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/eth1394.h
drivers/ieee1394/hosts.c
drivers/ieee1394/ieee1394-ioctl.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_transactions.h
drivers/ieee1394/ieee1394_types.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c

index 0b382a2af0e70532185ca34cff0f854960a42279..6e7b20f898c309d163b42de9f4e75de6248c8b7f 100644 (file)
@@ -74,6 +74,8 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 
@@ -1262,8 +1264,11 @@ MODULE_LICENSE("GPL");
 
 static int __init amdtp_init_module (void)
 {
-       if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
-                                     THIS_MODULE, &amdtp_fops)) {
+       int ret;
+
+       ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
+                                       THIS_MODULE, &amdtp_fops);
+       if (ret) {
                HPSB_ERR("amdtp: unable to get minor device block");
                return -EIO;
        }
@@ -1276,6 +1281,15 @@ static int __init amdtp_init_module (void)
                return -EIO;
        }
 
+#ifdef CONFIG_COMPAT
+       ret = register_ioctl32_conversion(AMDTP_IOC_CHANNEL, NULL);
+       ret |= register_ioctl32_conversion(AMDTP_IOC_PLUG, NULL);
+       ret |= register_ioctl32_conversion(AMDTP_IOC_PING, NULL);
+       ret |= register_ioctl32_conversion(AMDTP_IOC_ZAP, NULL);
+       if (ret)
+               HPSB_ERR("amdtp: Error registering ioctl32 translations");
+#endif
+
        HPSB_INFO("Loaded AMDTP driver");
 
        return 0;
@@ -1283,6 +1297,17 @@ static int __init amdtp_init_module (void)
 
 static void __exit amdtp_exit_module (void)
 {
+#ifdef CONFIG_COMPAT
+       int ret;
+
+       ret = unregister_ioctl32_conversion(AMDTP_IOC_CHANNEL);
+       ret |= unregister_ioctl32_conversion(AMDTP_IOC_PLUG);
+       ret |= unregister_ioctl32_conversion(AMDTP_IOC_PING);
+       ret |= unregister_ioctl32_conversion(AMDTP_IOC_ZAP);
+       if (ret)
+               HPSB_ERR("amdtp: Error unregistering ioctl32 translations");
+#endif
+
         hpsb_unregister_highlevel(amdtp_highlevel);
         ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
 
index eff68419f5fc449463dadb682af8ce3c4bf1b6c8..9ef4dbfc942c7ff56c3f9d68507605ee3aba76e9 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include "dma.h"
 
 /* dma_prog_region */
index 9e1252f34a598e268d0d16097fdf704d9d50a61c..09b0a29c62b347e9f9ec5915b935d5aca9209741 100644 (file)
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -2907,6 +2909,98 @@ static struct hpsb_highlevel_ops hl_ops = {
        .host_reset =   dv1394_host_reset,
 };
 
+#ifdef CONFIG_COMPAT
+
+#define DV1394_IOC32_INIT       _IOW('#', 0x06, struct dv1394_init32)
+#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
+
+struct dv1394_init32 {
+       u32 api_version;
+       u32 channel;
+       u32 n_frames;
+       u32 format;
+       u32 cip_n;
+       u32 cip_d;
+       u32 syt_offset;
+};
+
+struct dv1394_status32 {
+       struct dv1394_init32 init;
+       s32 active_frame;
+       u32 first_clear_frame;
+       u32 n_clear_frames;
+       u32 dropped_frames;
+};
+
+static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
+                             struct file *file)
+{
+       struct dv1394_init32 dv32;
+       struct dv1394_init dv;
+       mm_segment_t old_fs;
+       int ret;
+
+       if (file->f_op->ioctl != dv1394_ioctl)
+               return -EFAULT;
+
+       if (copy_from_user(&dv32, (void *)arg, sizeof(dv32)))
+               return -EFAULT;
+
+       dv.api_version = dv32.api_version;
+       dv.channel = dv32.channel;
+       dv.n_frames = dv32.n_frames;
+       dv.format = dv32.format;
+       dv.cip_n = (unsigned long)dv32.cip_n;
+       dv.cip_d = (unsigned long)dv32.cip_d;
+       dv.syt_offset = dv32.syt_offset;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+                          DV1394_IOC_INIT, (unsigned long)&dv);
+       set_fs(old_fs);
+
+       return ret;
+}
+
+static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
+                                   struct file *file)
+{
+       struct dv1394_status32 dv32;
+       struct dv1394_status dv;
+       mm_segment_t old_fs;
+       int ret;
+
+       if (file->f_op->ioctl != dv1394_ioctl)
+               return -EFAULT;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+                          DV1394_IOC_GET_STATUS, (unsigned long)&dv);
+       set_fs(old_fs);
+
+       if (!ret) {
+               dv32.init.api_version = dv.init.api_version;
+               dv32.init.channel = dv.init.channel;
+               dv32.init.n_frames = dv.init.n_frames;
+               dv32.init.format = dv.init.format;
+               dv32.init.cip_n = (u32)dv.init.cip_n;
+               dv32.init.cip_d = (u32)dv.init.cip_d;
+               dv32.init.syt_offset = dv.init.syt_offset;
+               dv32.active_frame = dv.active_frame;
+               dv32.first_clear_frame = dv.first_clear_frame;
+               dv32.n_clear_frames = dv.n_clear_frames;
+               dv32.dropped_frames = dv.dropped_frames;
+
+               if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32)))
+                       ret = -EFAULT;
+       }
+
+       return ret;
+}
+#endif /* CONFIG_COMPAT */
+
 
 /*** KERNEL MODULE HANDLERS ************************************************/
 
@@ -2917,6 +3011,20 @@ MODULE_LICENSE("GPL");
 
 static void __exit dv1394_exit_module(void)
 {
+#ifdef CONFIG_COMPAT
+       int ret;
+
+       ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
+       ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
+       if (ret)
+               printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
+#endif
+
        hpsb_unregister_highlevel (hl_handle);
        ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
@@ -2929,14 +3037,18 @@ static void __exit dv1394_exit_module(void)
 
 static int __init dv1394_init_module(void)
 {
-       if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
-                                     THIS_MODULE, &dv1394_fops)) {
+       int ret;
+
+       ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
+                                       THIS_MODULE, &dv1394_fops);
+       if (ret) {
                printk(KERN_ERR "dv1394: unable to register character device\n");
                return -EIO;
        }
 
 #ifdef CONFIG_DEVFS_FS
-       if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
+       ret = dv1394_devfs_add_dir("dv", NULL, NULL);
+       if (ret < 0) {
                printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
                ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
                return -ENOMEM;
@@ -2944,7 +3056,8 @@ static int __init dv1394_init_module(void)
 #endif
 
 #ifdef CONFIG_PROC_FS
-       if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) {
+       ret = dv1394_procfs_add_dir("dv",NULL,NULL);
+       if (ret < 0) {
                printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
                ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
@@ -2967,9 +3080,23 @@ static int __init dv1394_init_module(void)
                return -ENOMEM;
        }
 
+#ifdef CONFIG_COMPAT
+       /* First compatible ones */
+       ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
+       ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
+       ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
+       ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
+       ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
+
+       /* These need to be handled by translation */
+       ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
+       ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
+       if (ret)
+               printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
+#endif
+
        return 0;
 }
 
 module_init(dv1394_init_module);
 module_exit(dv1394_exit_module);
-
index 9aadf74fdefc52f2dca96d68450b84fb7acedd98..32b2e0c5f688e046f7c4869dfd698785166980ea 100644 (file)
@@ -65,6 +65,7 @@
 #include "ieee1394_transactions.h"
 #include "ieee1394.h"
 #include "highlevel.h"
+#include "iso.h"
 #include "eth1394.h"
 
 #define ETH1394_PRINT_G(level, fmt, args...) \
@@ -77,7 +78,7 @@
        printk(KERN_ERR fmt, ## args)
 
 static char version[] __devinitdata =
-       "$Rev: 770 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 801 $ Ben Collins <bcollins@debian.org>";
 
 /* Our ieee1394 highlevel driver */
 #define ETHER1394_DRIVER_NAME "ether1394"
@@ -101,6 +102,9 @@ MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
 MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
 MODULE_LICENSE("GPL");
 
+static void ether1394_iso(struct hpsb_iso *iso);
+
+
 /* Find our host_info struct for a given host pointer. Must be called
  * under spinlock.  */
 static inline struct host_info *find_host_info (struct hpsb_host *host)
@@ -178,15 +182,26 @@ static void ether1394_tx_timeout (struct net_device *dev)
  * XXX: This is where we need to create a list of skb's for fragmented
  * packets.  */
 static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev,
-                           int proto)
+                                          int proto, struct packet_task *ptask)
 {
        union eth1394_hdr *hdr =
                (union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]);
 
+       hdr->words.word1 = 0;
        hdr->common.lf = ETH1394_HDR_LF_UF;
        hdr->words.word1 = htons(hdr->words.word1);
        hdr->uf.ether_type = proto;
 
+       /* Set the transmission type for the packet.  Right now only ARP
+        * packets are sent via GASP.  IP broadcast and IP multicast are not
+        * yet supported properly, they too should use GASP. */
+       switch(proto) {
+       case __constant_htons(ETH_P_ARP):
+               ptask->tx_type = ETH1394_GASP;
+               break;
+       default:
+               ptask->tx_type = ETH1394_WRREQ;
+       }
        return;
 }
 
@@ -199,7 +214,7 @@ static inline void ether1394_arp_to_1394arp (struct sk_buff *skb, struct net_dev
 {
        struct eth1394_priv *priv =
                (struct eth1394_priv *)(dev->priv);
-       u16 phy_id = priv->host->node_id & NODE_MASK;
+       u16 phy_id = NODEID_TO_NODE(priv->host->node_id);
 
        unsigned char *arp_ptr = (unsigned char *)skb->data;
        struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
@@ -279,7 +294,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
 {
        unsigned long flags;
        struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-       int phy_id = priv->host->node_id & NODE_MASK;
+       int phy_id = NODEID_TO_NODE(priv->host->node_id);
+       struct hpsb_host *host = priv->host;
 
        spin_lock_irqsave (&priv->lock, flags);
 
@@ -289,20 +305,23 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
        memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi));
        memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));
 
+       priv->bc_state = ETHER1394_BC_CHECK;
+
        /* Register our limits now */
-       ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf,
-                                  priv->host->speed_map[(phy_id << 6) + phy_id],
-                                  (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) |
-                                  be32_to_cpu(priv->host->csr.rom[4])),
+       ether1394_register_limits (phy_id, (be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf,
+                                  host->speed_map[(phy_id << 6) + phy_id],
+                                  (u64)(((u64)be32_to_cpu(host->csr.rom[3]) << 32) |
+                                  be32_to_cpu(host->csr.rom[4])),
                                   ETHER1394_REGION_ADDR >> 32,
                                   ETHER1394_REGION_ADDR & 0xffffffff, priv);
 
        /* We'll use our max_rec as the default mtu */
        if (set_mtu)
-               dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr);
+               dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */
+                       (sizeof (union eth1394_hdr) + 8);       /* (hdr + GASP) */
 
        /* Set our hardware address while we're at it */
-       *(nodeid_t *)dev->dev_addr = htons (priv->host->node_id);
+       *(nodeid_t *)dev->dev_addr = htons (host->node_id);
 
        spin_unlock_irqrestore (&priv->lock, flags);
 }
@@ -383,6 +402,15 @@ static void ether1394_add_host (struct hpsb_host *host)
        list_add_tail (&hi->list, &host_info_list);
        spin_unlock_irq (&host_info_lock);
 
+       /* Ignore validity in hopes that it will be set in the future.  It'll
+        * check it on transmit. */
+       priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
+
+       priv->iso = hpsb_iso_recv_init(host, 8 * 4096, 8, priv->broadcast_channel,
+                                      1, ether1394_iso);
+       if (priv->iso == NULL) {
+               priv->bc_state = ETHER1394_BC_CLOSED;
+       }
        return;
 
 out:
@@ -396,11 +424,14 @@ out:
 /* Remove a card from our list */
 static void ether1394_remove_host (struct hpsb_host *host)
 {
+       struct eth1394_priv *priv;
        struct host_info *hi;
 
        spin_lock_irq (&host_info_lock);
        hi = find_host_info (host);
        if (hi != NULL) {
+               priv = (struct eth1394_priv *)hi->dev->priv;
+               priv->bc_state = ETHER1394_BC_CLOSED;
                unregister_netdev (hi->dev);
                kfree (hi->dev);
                list_del (&hi->list);
@@ -480,7 +511,7 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
         * about the sending machine.  */
        if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) {
                unsigned long flags;
-               u16 phy_id = srcid & NODE_MASK;
+               u16 phy_id = NODEID_TO_NODE(srcid);
                struct eth1394_priv *priv =
                        (struct eth1394_priv *)dev->priv;
                struct eth1394_arp arp1394;
@@ -591,6 +622,104 @@ bad_proto:
        return RCODE_COMPLETE;
 }
 
+static void ether1394_iso(struct hpsb_iso *iso)
+{
+       struct sk_buff *skb;
+       quadlet_t *data;
+       char *buf;
+       int flags;
+       struct net_device *dev = ether1394_find_dev(iso->host);
+       struct eth1394_priv *priv;
+       unsigned int len;
+       u32 specifier_id;
+       u16 source_id;
+       int i;
+       int nready;
+
+       if (dev == NULL) {
+               ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n",
+                                iso->host->driver->name);
+               return;
+       }
+
+       nready = hpsb_iso_n_ready(iso);
+       for(i = 0; i < nready; i++) {
+               struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i];
+               data = (quadlet_t*) (iso->data_buf.kvirt + info->offset);
+
+               /* skip over GASP header */
+               buf = (char *)data + 8;
+               len = info->len - 8;
+
+               specifier_id = (((be32_to_cpu(data[0]) & 0xffff) << 8) |
+                               ((be32_to_cpu(data[1]) & 0xff000000) >> 24));
+               source_id = be32_to_cpu(data[0]) >> 16;
+
+               priv = (struct eth1394_priv *)dev->priv;
+
+               if (info->channel != priv->broadcast_channel ||
+                   specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
+                       /* This packet is not for us */
+                       continue;
+               }
+
+               /* A packet has been received by the ieee1394 bus. Build an skbuff
+                * around it so we can pass it to the high level network layer. */
+               skb = dev_alloc_skb (len + dev->hard_header_len + 15);
+               if (!skb) {
+                       HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
+                       priv->stats.rx_dropped++;
+                       break;
+               }
+
+               skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
+
+               memcpy (skb_put (skb, len), buf, len);
+
+               /* Write metadata, and then pass to the receive level */
+               skb->dev = dev;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;  /* don't check it */
+
+               /* Parse the encapsulation header. This actually does the job of
+                * converting to an ethernet frame header, aswell as arp
+                * conversion if needed. ARP conversion is easier in this
+                * direction, since we are using ethernet as our backend.  */
+               skb->protocol = ether1394_parse_encap (skb, dev, source_id,
+                                                      LOCAL_BUS | ALL_NODES);
+
+               spin_lock_irqsave (&priv->lock, flags);
+               if (!skb->protocol) {
+                       priv->stats.rx_errors++;
+                       priv->stats.rx_dropped++;
+                       dev_kfree_skb_any(skb);
+                       goto bad_proto;
+               }
+
+               netif_stop_queue(dev);
+               if (netif_rx (skb) == NET_RX_DROP) {
+                       priv->stats.rx_errors++;
+                       priv->stats.rx_dropped++;
+                       goto bad_proto;
+               }
+
+               /* Statistics */
+               priv->stats.rx_packets++;
+               priv->stats.rx_bytes += skb->len;
+
+       bad_proto:
+               spin_unlock_irqrestore (&priv->lock, flags);
+       }
+
+       hpsb_iso_recv_release_packets(iso, i);
+
+       netif_start_queue(dev);
+       
+       dev->last_rx = jiffies;
+
+       return;
+}
+
+
 /* This function is our scheduled write */
 static void hpsb_write_sched (void *__ptask)
 {
@@ -598,13 +727,26 @@ static void hpsb_write_sched (void *__ptask)
        struct sk_buff *skb = ptask->skb;
        struct net_device *dev = ptask->skb->dev;
        struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-        unsigned long flags;
+       unsigned long flags;
+       int status;
+ 
+       if (ptask->tx_type == ETH1394_GASP) {
+               status  = hpsb_send_gasp(priv->host, priv->broadcast_channel,
+                                        get_hpsb_generation(priv->host),
+                                        (quadlet_t *)skb->data, skb->len,
+                                        ETHER1394_GASP_SPECIFIER_ID,
+                                        ETHER1394_GASP_VERSION);
+       } else {
+               status = hpsb_write(priv->host, ptask->dest_node,
+                                   get_hpsb_generation(priv->host),
+                                   ptask->addr, (quadlet_t *)skb->data,
+                                   skb->len);
+       }
+
 
        /* Statistics */
        spin_lock_irqsave (&priv->lock, flags);
-       if (!hpsb_write(priv->host, ptask->dest_node,
-                       get_hpsb_generation(priv->host),
-                       ptask->addr, (quadlet_t *)skb->data, skb->len)) {
+       if (!status) {
                priv->stats.tx_bytes += skb->len;
                priv->stats.tx_packets++;
        } else {
@@ -636,6 +778,67 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
        struct packet_task *ptask = NULL;
        int ret = 0;
 
+       spin_lock_irqsave (&priv->lock, flags);
+       if (priv->bc_state == ETHER1394_BC_CLOSED) {
+               ETH1394_PRINT(KERN_ERR, dev->name,
+                             "Cannot send packet, no broadcast channel available.");
+               ret = -EAGAIN;
+               goto fail;
+       }
+
+       /* First time sending?  Need a broadcast channel for ARP and for
+        * listening on */
+       if (priv->bc_state == ETHER1394_BC_CHECK) {
+               quadlet_t bc;
+
+               /* Get the local copy of the broadcast channel and check its
+                * validity (the IRM should validate it for us) */
+
+               bc = priv->host->csr.broadcast_channel;
+
+               if ((bc & 0xc0000000) != 0xc0000000) {
+                       /* broadcast channel not validated yet */
+                       ETH1394_PRINT(KERN_WARNING, dev->name,
+                                     "Error BROADCAST_CHANNEL register valid "
+                                     "bit not set, can't send IP traffic\n");
+                       hpsb_iso_shutdown(priv->iso);
+                       priv->bc_state = ETHER1394_BC_CLOSED;
+                       ret = -EAGAIN;
+                       spin_unlock_irqrestore (&priv->lock, flags);
+                       goto fail;
+               }
+               if (priv->broadcast_channel != (bc & 0x3f)) {
+                       /* This really shouldn't be possible, but just in case
+                        * the IEEE 1394 spec changes regarding broadcast
+                        * channels in the future. */
+                       hpsb_iso_shutdown(priv->iso);
+
+                       priv->broadcast_channel = bc & 0x3f;
+                       ETH1394_PRINT(KERN_WARNING, dev->name,
+                                     "Changing to broadcast channel %d...\n",
+                                     priv->broadcast_channel);
+
+                       priv->iso = hpsb_iso_recv_init(priv->host, 8 * 4096,
+                                                      8, priv->broadcast_channel,
+                                                      1, ether1394_iso);
+                       if (priv->iso == NULL) {
+                               ret = -EAGAIN;
+                               goto fail;
+                       }
+               }
+               if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {
+                       ETH1394_PRINT(KERN_ERR, dev->name,
+                                     "Could not start async reception\n");
+                       hpsb_iso_shutdown(priv->iso);
+                       priv->bc_state = ETHER1394_BC_CLOSED;
+                       ret = -EAGAIN;
+                       spin_unlock_irqrestore (&priv->lock, flags);
+                       goto fail;
+               }
+               priv->bc_state = ETHER1394_BC_OPENED;
+       }
+       spin_unlock_irqrestore (&priv->lock, flags);
+
        if ((skb = skb_share_check (skb, kmflags)) == NULL) {
                ret = -ENOMEM;
                goto fail;
@@ -654,8 +857,14 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
        if (proto == __constant_htons (ETH_P_ARP))
                ether1394_arp_to_1394arp (skb, dev);
 
+       ptask = kmem_cache_alloc(packet_task_cache, kmflags);
+       if (ptask == NULL) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
        /* Now add our encapsulation header */
-       ether1394_encapsulate (skb, dev, proto);
+       ether1394_encapsulate (skb, dev, proto, ptask);
 
        /* TODO: The above encapsulate function needs to recognize when a
         * packet needs to be split for a specified node. It should create
@@ -667,19 +876,13 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
         * need this hack.  */
 
        spin_lock_irqsave (&priv->lock, flags);
-       addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 |
-               priv->fifo_lo[dest_node & NODE_MASK];
+       addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 |
+               priv->fifo_lo[NODEID_TO_NODE(dest_node)];
        spin_unlock_irqrestore (&priv->lock, flags);
 
        if (!addr)
                addr = ETHER1394_REGION_ADDR;
 
-       ptask = kmem_cache_alloc(packet_task_cache, kmflags);
-       if (ptask == NULL) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
        ptask->skb = skb;
        ptask->addr = addr;
        ptask->dest_node = dest_node;
@@ -702,7 +905,7 @@ fail:
                netif_wake_queue (dev);
        spin_unlock_irqrestore (&priv->lock, flags);
 
-       return ret;
+       return 0;  /* returning non-zero causes serious problems */
 }
 
 /* Function for incoming 1394 packets */
@@ -738,6 +941,19 @@ static int __init ether1394_init_module (void)
 
 static void __exit ether1394_exit_module (void)
 {
+       struct list_head *lh;
+       struct host_info *hi;
+       struct eth1394_priv *priv;
+
+       lh = host_info_list.next;
+       while (lh != &host_info_list) {
+               hi = list_entry (lh, struct host_info, list);
+               priv = (struct eth1394_priv*)hi->dev->priv;
+               if (priv->bc_state != ETHER1394_BC_CLOSED) {
+                       hpsb_iso_shutdown(priv->iso);
+               }
+               lh = lh->next;
+       }
        hpsb_unregister_highlevel (hl_handle);
        kmem_cache_destroy(packet_task_cache);
 }
index 44c1637182c6a17afb18e8c7325f0459c72f6500..1c38fb02cdfe82a0fcbe40e48cccbb267dca1153 100644 (file)
 #define ETHER1394_REGION_ADDR          0xfffff0200000ULL
 #define ETHER1394_REGION_ADDR_END      (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
 
+/* GASP identifier numbers for IPv4 over IEEE 1394 */
+#define ETHER1394_GASP_SPECIFIER_ID    0x00005E
+#define ETHER1394_GASP_VERSION         1
+
 /* Node set == 64 */
 #define NODE_SET                       (ALL_NODES + 1)
 
+enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
+                        ETHER1394_BC_CHECK };
+
 /* Private structure for our ethernet driver */
 struct eth1394_priv {
        struct net_device_stats stats;  /* Device stats                  */
@@ -43,6 +50,9 @@ struct eth1394_priv {
        u32 fifo_lo[ALL_NODES];         /* 32bit lo fifo offset per node */
        u64 eui[ALL_NODES];             /* EUI-64 per node               */
        spinlock_t lock;                /* Private lock                  */
+       int broadcast_channel;          /* Async stream Broadcast Channel */
+       enum eth1394_bc_states bc_state; /* broadcast channel state      */
+       struct hpsb_iso *iso;           /* Async stream recv handle      */
 };
 
 struct host_info {
@@ -51,12 +61,15 @@ struct host_info {
        struct net_device *dev;
 };
 
+typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
+
 /* This is our task struct. It's used for the packet complete callback.  */
 struct packet_task {
        struct sk_buff *skb;    /* Socket buffer we are sending */
        nodeid_t dest_node;     /* Destination of the packet */
        u64 addr;               /* Address */
        struct hpsb_queue_struct tq;    /* The task */
+       eth1394_tx_type tx_type;        /* Send data via GASP or Write Req. */
 };
 
 /* IP1394 headers */
index f6669023152b768acb740215a9892de12f5b4a6f..fba9fb09c89f6f2477cb396351c6fab480174b4b 100644 (file)
@@ -71,9 +71,6 @@ int hpsb_ref_host(struct hpsb_host *host)
         list_for_each(lh, &hosts) {
                 if (host == list_entry(lh, struct hpsb_host, host_list)) {
                        if (try_module_get(host->driver->owner)) {
-                               /* we're doing this twice and don't seem
-                                  to undo it..  --hch */
-                               (void)try_module_get(host->driver->owner);
                                host->refcount++;
                                retval = 1;
                        }
index d9d99bc2706c72524601005f9677898d57b50de1..1091bdff1391fcf02dae1fca328931feb740c0db 100644 (file)
@@ -4,8 +4,8 @@
 #ifndef __IEEE1394_IOCTL_H
 #define __IEEE1394_IOCTL_H
 
-#include <asm/ioctl.h>
-#include <asm/types.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
 
 
 /* AMDTP Gets 6 */
@@ -91,7 +91,7 @@
 #define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL  \
        _IOW ('#', 0x23, unsigned char)
 #define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK  \
-       _IOW ('#', 0x24, u64)
+       _IOW ('#', 0x24, __u64)
 #define RAW1394_IOC_ISO_RECV_PACKETS           \
        _IOW ('#', 0x25, struct raw1394_iso_packets)
 #define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS   \
index 35b5571efd0450b4c6c9a9082b6c1b8cc11ec977..ea7c5c189d142b99c63f2005247ac9113c5219d7 100644 (file)
@@ -361,7 +361,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
                 host->topology_map[host->selfid_count++] = sid;
         } else {
                 HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
-                           sid, (host->node_id & BUS_MASK) >> 6);
+                           sid, NODEID_TO_BUS(host->node_id));
         }
 }
 
@@ -396,9 +396,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
         /* 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;
@@ -535,8 +532,8 @@ int hpsb_send_packet(struct hpsb_packet *packet)
 
         if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
                 packet->speed_code =
-                        host->speed_map[(host->node_id & NODE_MASK) * 64
-                                       + (packet->node_id & NODE_MASK)];
+                        host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+                                       + NODEID_TO_NODE(packet->node_id)];
         }
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
@@ -748,7 +745,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                                        addr, 4, flags);
 
                 if (!write_acked
-                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
                     && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
@@ -763,7 +760,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
                                        addr, data[3]>>16, flags);
 
                 if (!write_acked
-                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
                     && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
@@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_lock64);
+EXPORT_SYMBOL(hpsb_send_gasp);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
index 8802070a3d612885103ac63849439c06737068a5..7b5a6af2296879a7bc6f84ba1935f36a3a2033c6 100644 (file)
@@ -98,6 +98,17 @@ static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
         packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
 }
 
+static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
+                                    int channel, int tag, int sync)
+{
+       packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+               | (TCODE_STREAM_DATA << 4) | sync;
+
+       packet->header_size = 4;
+       packet->data_size = length;
+       packet->type = hpsb_async;
+       packet->tcode = TCODE_ISO_DATA;
+}
 
 /**
  * hpsb_get_tlabel - allocate a transaction label
@@ -495,7 +506,6 @@ hpsb_write_fail:
 }
 
 
-/* We need a hpsb_lock64 function for the 64 bit equivalent.  Probably. */
 int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
              u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
 {
@@ -558,3 +568,58 @@ hpsb_lock64_fail:
 
         return retval;
 }
+
+int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
+                  quadlet_t *buffer, size_t length, u32 specifier_id,
+                  unsigned int version)
+{
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       int i;
+#endif
+
+       struct hpsb_packet *packet;
+       int retval = 0;
+       u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
+       u8 specifier_id_lo = specifier_id & 0xff;
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length);
+#endif
+
+       length += 8;
+
+       packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+       if (!packet)
+               return -ENOMEM;
+
+       if (length % 4) {
+               packet->data[length / 4] = 0;
+       }
+
+       packet->host = host;
+       fill_async_stream_packet(packet, length, channel, 3, 0);
+        
+       packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
+       packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+
+       memcpy(&(packet->data[2]), buffer, length - 4);
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size);
+       HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size);
+
+       for(i=0; i<(packet->data_size/4); i++)
+               HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i]));
+#endif
+
+       packet->generation = generation;
+
+       packet->no_waiter = 1;
+
+       if (!hpsb_send_packet(packet)) {
+               free_hpsb_packet(packet);
+               retval = -EINVAL;
+       }
+
+       return retval;
+}
index 3750e40c0bc7a061a7d8483152ef62ad1de16aad..5cbcec56b82d5a1edb165da5a42d7bf9990d591b 100644 (file)
@@ -55,5 +55,8 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
              u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
                u64 addr, int extcode, octlet_t *data, octlet_t arg);
+int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
+                   quadlet_t *buffer, size_t length, u32 specifier_id,
+                   unsigned int version);
 
 #endif /* _IEEE1394_TRANSACTIONS_H */
index 691705cd1286982fe10d34389c888be9df5b943c..95b8965bb2bd1da060ad2ab71a6da20293c823ff 100644 (file)
@@ -97,14 +97,17 @@ typedef u64 nodeaddr_t;
 typedef u16 arm_length_t;
 
 #define BUS_MASK  0xffc0
+#define BUS_SHIFT 6
 #define NODE_MASK 0x003f
 #define LOCAL_BUS 0xffc0
 #define ALL_NODES 0x003f
 
+#define NODEID_TO_BUS(nodeid)  ((nodeid & BUS_MASK) >> BUS_SHIFT)
+#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
+
 /* Can be used to consistently print a node/bus ID. */
-#define NODE_BUS_FMT    "%02d:%04d"
-#define NODE_BUS_ARGS(nodeid) \
-       (nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
+#define NODE_BUS_FMT           "%02d:%04d"
+#define NODE_BUS_ARGS(nodeid)  NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
 
 #define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
 
index 970aa1e09de65828dca119c2775067a4f915bb64..72412bcfe1d5700ec7507c1537a0c04bbef4e8a8 100644 (file)
@@ -1210,6 +1210,52 @@ static void nodemgr_node_probe(struct hpsb_host *host)
        return;
 }
 
+/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
+ * nodes of the broadcast channel.  (Really we're only setting the validity
+ * bit). */
+static void nodemgr_do_irm_duties(struct hpsb_host *host)
+{
+       quadlet_t bc;
+        
+       if (!host->is_irm)
+               return;
+
+       host->csr.broadcast_channel |= 0x40000000;  /* set validity bit */
+
+       bc = cpu_to_be32(host->csr.broadcast_channel);
+
+       hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
+                  (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
+                  &bc,
+                  sizeof(quadlet_t));
+}
+
+/* We need to ensure that if we are not the IRM, that the IRM node is capable of
+ * everything we can do, otherwise issue a bus reset and try to become the IRM
+ * ourselves. */
+static int nodemgr_check_root_capability(struct hpsb_host *host)
+{
+       quadlet_t bc;
+       int status;
+
+       if (host->is_irm)
+               return 1;
+
+       status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
+                          get_hpsb_generation(host),
+                          (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
+                          &bc, sizeof(quadlet_t));
+
+       if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
+               /* The root node does not have a valid BROADCAST_CHANNEL
+                * register and we do, so reset the bus with force_root set */
+               HPSB_INFO("Remote root is not IRM capable, resetting...");
+               hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
+               return 0;
+       }
+       return 1;
+}
+
 static int nodemgr_host_thread(void *__hi)
 {
        struct host_info *hi = (struct host_info *)__hi;
@@ -1217,12 +1263,21 @@ static int nodemgr_host_thread(void *__hi)
        /* No userlevel access needed */
        daemonize("knodemgrd");
        allow_signal(SIGTERM);
-
+       
        /* Sit and wait for a signal to probe the nodes on the bus. This
         * happens when we get a bus reset. */
        while (!down_interruptible(&hi->reset_sem) &&
               !down_interruptible(&nodemgr_serialize)) {
+
+               if (!nodemgr_check_root_capability(hi->host)) {
+                       /* Do nothing, we are resetting */
+                       up(&nodemgr_serialize);
+                       continue;
+               }
+
                nodemgr_node_probe(hi->host);
+               nodemgr_do_irm_duties(hi->host);
+
                up(&nodemgr_serialize);
        }
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
index ea268b5b071bb43bee096b16fccf8ac88be488a2..9da0dce7b83fe4bb03855c547fba480bf0bd98d2 100644 (file)
@@ -31,9 +31,9 @@
  *
  * Things implemented, but still in test phase:
  * . Iso Transmit
+ * . Async Stream Packets Transmit (Receive done via Iso interface)
  * 
  * Things not implemented:
- * . Async Stream Packets
  * . DMA error recovery
  *
  * Known bugs:
@@ -160,7 +160,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: 762 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 801 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(phys_dma,"i");
@@ -649,18 +649,31 @@ static void insert_packet(struct ti_ohci *ohci,
                 } else {
                         d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
                                 (packet->header[0] & 0xFFFF);
-                        d->prg_cpu[idx]->data[1] =
-                                (packet->header[1] & 0xFFFF) | 
-                                (packet->header[0] & 0xFFFF0000);
-                        d->prg_cpu[idx]->data[2] = packet->header[2];
-                        d->prg_cpu[idx]->data[3] = packet->header[3];
+
+                       if (packet->tcode == TCODE_ISO_DATA) {
+                               /* Sending an async stream packet */
+                               d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
+                       } else {
+                               /* Sending a normal async request or response */
+                               d->prg_cpu[idx]->data[1] =
+                                       (packet->header[1] & 0xFFFF) | 
+                                       (packet->header[0] & 0xFFFF0000);
+                               d->prg_cpu[idx]->data[2] = packet->header[2];
+                               d->prg_cpu[idx]->data[3] = packet->header[3];
+                       }
                        packet_swab(d->prg_cpu[idx]->data, packet->tcode);
                 }
 
                 if (packet->data_size) { /* block transmit */
-                        d->prg_cpu[idx]->begin.control =
-                                cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                           DMA_CTL_IMMEDIATE | 0x10);
+                       if (packet->tcode == TCODE_STREAM_DATA){
+                               d->prg_cpu[idx]->begin.control =
+                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+                                                   DMA_CTL_IMMEDIATE | 0x8);
+                       } else {
+                               d->prg_cpu[idx]->begin.control =
+                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+                                                   DMA_CTL_IMMEDIATE | 0x10);
+                       }
                         d->prg_cpu[idx]->end.control =
                                 cpu_to_le32(DMA_CTL_OUTPUT_LAST |
                                            DMA_CTL_IRQ | 
@@ -830,7 +843,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
        /* Decide whether we have an iso, a request, or a response packet */
        if (packet->type == hpsb_raw)
                d = &ohci->at_req_context;
-       else if (packet->tcode == TCODE_ISO_DATA) {
+       else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
                /* The legacy IT DMA context is initialized on first
                 * use.  However, the alloc cannot be run from
                 * interrupt context, so we bail out if that is the
@@ -856,7 +869,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
                }
                
                d = &ohci->it_legacy_context;
-       } else if (packet->tcode & 0x02)
+       } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
                d = &ohci->at_resp_context;
        else 
                d = &ohci->at_req_context;
@@ -1295,6 +1308,8 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
        u32 *prev_branch = NULL;
 
        for (blk = 0; blk < recv->nblocks; blk++) {
+               u32 control;
+
                /* the DMA descriptor */
                struct dma_cmd *cmd = &recv->block[blk];
 
@@ -1305,29 +1320,29 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
                unsigned long buf_offset = blk * recv->buf_stride;
 
                if (recv->dma_mode == BUFFER_FILL_MODE) {
-                       cmd->control = 2 << 28; /* INPUT_MORE */
+                       control = 2 << 28; /* INPUT_MORE */
                } else {
-                       cmd->control = 3 << 28; /* INPUT_LAST */
+                       control = 3 << 28; /* INPUT_LAST */
                }
 
-               cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
+               control |= 8 << 24; /* s = 1, update xferStatus and resCount */
 
                /* interrupt on last block, and at intervals */
                if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
-                       cmd->control |= 3 << 20; /* want interrupt */
+                       control |= 3 << 20; /* want interrupt */
                }
 
-               cmd->control |= 3 << 18; /* enable branch to address */
-               cmd->control |= recv->buf_stride;
+               control |= 3 << 18; /* enable branch to address */
+               control |= recv->buf_stride;
 
-               cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset);
+               cmd->control = cpu_to_le32(control);
+               cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
                cmd->branchAddress = 0; /* filled in on next loop */
-               cmd->status = recv->buf_stride;
+               cmd->status = cpu_to_le32(recv->buf_stride);
 
                /* link the previous descriptor to this one */
                if (prev_branch) {
-                       *prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset);
-                       *prev_branch |= 1; /* set Z=1 */
+                       *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
                }
 
                prev_branch = &cmd->branchAddress;
@@ -1485,18 +1500,18 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
        /* 'next' becomes the new end of the DMA chain,
           so disable branch and enable interrupt */
        next->branchAddress = 0;
-       next->control |= 3 << 20;
+       next->control |= cpu_to_le32(3 << 20);
 
        /* link prev to next */ 
-       prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
-                                                           sizeof(struct dma_cmd) * next_i)
-               | 1; /* Z=1 */
+       prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
+                                                                       sizeof(struct dma_cmd) * next_i)
+                                         | 1); /* Z=1 */
 
        /* disable interrupt on previous DMA descriptor, except at intervals */
        if((prev_i % recv->block_irq_interval) == 0) {
-               prev->control |= 3 << 20; /* enable interrupt */
+               prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
        } else {
-               prev->control &= ~(3<<20); /* disable interrupt */
+               prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
        }
        wmb();
 
@@ -1720,8 +1735,8 @@ static void ohci_iso_recv_packetperbuf_task(unsigned long data)
                struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
 
                /* check the DMA descriptor for new writes to xferStatus */
-               u16 xferstatus = il->status >> 16;
-               u16 rescount = il->status & 0xFFFF;
+               u16 xferstatus = le32_to_cpu(il->status) >> 16;
+               u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
 
                unsigned char event = xferstatus & 0x1F;
 
@@ -1903,7 +1918,7 @@ static void ohci_iso_xmit_task(unsigned long data)
                struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
                
                /* check for new writes to xferStatus */
-               u16 xferstatus = cmd->output_last.status >> 16;
+               u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
                u8  event = xferstatus & 0x1F;
 
                if(!event) {
@@ -1919,7 +1934,7 @@ static void ohci_iso_xmit_task(unsigned long data)
                wake = 1;
                
                /* parse cycle */
-               cycle = cmd->output_last.status & 0x1FFF;
+               cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
 
                /* tell the subsystem the packet has gone out */
                hpsb_iso_packet_sent(iso, cycle, event != 0x11);
@@ -1972,7 +1987,7 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
 
        /* set up the OUTPUT_MORE_IMMEDIATE descriptor */
        memset(next, 0, sizeof(struct iso_xmit_cmd));
-       next->output_more_immediate.control = 0x02000008;
+       next->output_more_immediate.control = cpu_to_le32(0x02000008);
 
        /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
 
@@ -1990,28 +2005,28 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
        next->iso_hdr[7] = len >> 8;
 
        /* set up the OUTPUT_LAST */
-       next->output_last.control = 1 << 28;
-       next->output_last.control |= 1 << 27; /* update timeStamp */
-       next->output_last.control |= 3 << 20; /* want interrupt */
-       next->output_last.control |= 3 << 18; /* enable branch */
-       next->output_last.control |= len;
+       next->output_last.control = cpu_to_le32(1 << 28);
+       next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
+       next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
+       next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
+       next->output_last.control |= cpu_to_le32(len);
 
        /* payload bus address */
-       next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset);
+       next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset));
 
        /* leave branchAddress at zero for now */
 
        /* re-write the previous DMA descriptor to chain to this one */
 
        /* set prev branch address to point to next (Z=3) */
-       prev->output_last.branchAddress =
-               dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3;
+       prev->output_last.branchAddress = cpu_to_le32(
+               dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
 
        /* disable interrupt, unless required by the IRQ interval */
        if(prev_i % iso->irq_interval) {
-               prev->output_last.control &= ~(3 << 20); /* no interrupt */
+               prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
        } else {
-               prev->output_last.control |= 3 << 20; /* enable interrupt */
+               prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
        }
 
        wmb();
@@ -3473,10 +3488,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
 
 static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
        {
-               .class =                PCI_CLASS_FIREWIRE_OHCI,
-               .class_mask =   0x00ffffff,
-               .vendor =               PCI_ANY_ID,
-               .device =               PCI_ANY_ID,
+               .class =        PCI_CLASS_FIREWIRE_OHCI,
+               .class_mask =   ~0,
+               .vendor =       PCI_ANY_ID,
+               .device =       PCI_ANY_ID,
                .subvendor =    PCI_ANY_ID,
                .subdevice =    PCI_ANY_ID,
        },
index e93bc36a77ef4eb27ef19fe052c3ca0b124517e9..6bbfd38d95db30a7c4d48ba4f70621b8fd56418a 100644 (file)
@@ -238,7 +238,7 @@ static void remove_host(struct hpsb_host *host)
                 list_del(&hi->list);
                 host_count--;
                 /* 
-                   FIXME: addressranges should be removed 
+                   FIXME: address ranges should be removed 
                    and fileinfo states should be initialized
                    (including setting generation to 
                    internal-generation ...)
@@ -281,8 +281,8 @@ static void host_reset(struct hpsb_host *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);
+                                                req->req.misc |= (NODEID_TO_NODE(host->irm_id)
+                                                                  << 8);
                                         }
 
                                         queue_complete_req(req);
@@ -571,8 +571,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
                         req->req.misc = (fi->host->node_id << 16) 
                                 | fi->host->node_count;
                         if (fi->protocol_version > 3) {
-                                req->req.misc |=
-                                        (fi->host->irm_id & NODE_MASK) << 8;
+                                req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
                         }
                 } else {
                         req->req.error = RAW1394_ERROR_INVALID_ARG;
index e5631a8268c474863bb9e4563260e6c9d9d6d4bc..dbeb597a683e788cdf473d919acc34cba26099ce 100644 (file)
  * driver. It also registers as a SCSI lower-level driver in order to accept
  * SCSI commands for transport using SBP-2.
  *
- *
- * Driver Loading:
- *
- * Currently, the SBP-2 driver is supported only as a module. Because the 
- * Linux SCSI stack is not Plug-N-Play aware, module load order is 
- * important. Assuming the SCSI core drivers are either built into the 
- * kernel or already loaded as modules, you should load the IEEE-1394 modules 
- * in the following order:
- *
- *     ieee1394 (e.g. insmod ieee1394)
- *     ohci1394 (e.g. insmod ohci1394)
- *     sbp2 (e.g. insmod sbp2)
- *
- * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first
- * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print 
- * out a debug message indicating if it was able to discover a SBP-2 device.
- *
- * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the
- * initial scsi bus scan (when the driver is first loaded). To add or remove
- * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a 
- * device after the SBP-2 driver is loaded), you must either use the scsi procfs
- * add-single-device, remove-single-device, or a shell script such as 
- * rescan-scsi-bus.sh.
- *
  * The easiest way to add/detect new SBP-2 devices is to run the shell script
  * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be 
  * found at:
  *     - Error Handling: SCSI aborts and bus reset requests are handled somewhat
  *       but the code needs additional debugging.
  *
- *     - Module: The SBP-2 driver is currently only supported as a module. It would not take
- *       much work to allow it to be compiled into the kernel, but you'd have to 
- *       add some init code to the kernel to support this... and modules are much
- *       more flexible anyway.   ;-)
- *
- *     - Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could
- *       stand some improvement.
- *
  *
  * History:
  *
  *     04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it
  *                returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one.
  *     04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG)
- *     06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG)   
+ *     06/09/02 - Don't force 36-byte SCSI inquiry, but leave in a define for badly behaved devices. (JSG)   
  *     02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command).
  *                Also save/restore irq flags in sbp2scsi_complete_command  - Sancho Dauskardt <sda@bdit.de>
  *     02/06/03 - Removed spinlock debugging; use kernel stuff instead (sda)
+ *     02/10/03 - Adopt to new hot-plug aware SCSI inferface (hch@lst.de)
  *
  */
 
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-       "$Rev: 779 $ James Goodwin <jamesg@filanet.com>";
+       "$Rev: 797 $ James Goodwin <jamesg@filanet.com>";
 
 /*
  * Module load parameter definitions
@@ -497,6 +466,15 @@ static u32 global_outstanding_dmas = 0;
  * Globals
  */
 
+static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi,
+                                          struct scsi_id_instance_data *scsi_id,
+                                          u32 status);
+
+static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi,
+                                     struct scsi_id_instance_data *scsi_id,
+                                     u32 scsi_status, Scsi_Cmnd *SCpnt,
+                                     void (*done)(Scsi_Cmnd *));
+       
 static Scsi_Host_Template scsi_driver_template;
 
 static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };
@@ -822,7 +800,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
 {
        struct sbp2scsi_host_info *hi;
        
-       hi = (struct sbp2scsi_host_info *) command->Current_SCpnt->device->host->hostdata[0];
+       hi = (struct sbp2scsi_host_info *)&command->Current_SCpnt->device->host->hostdata;
 
        if (hi == NULL) {
                printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__);
@@ -871,59 +849,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
  * IEEE-1394 core driver stack related section
  *********************************************/
 
-/*
- * This function is called at SCSI init in order to register our driver
- * with the IEEE-1394 stack.
- */
-int sbp2_init(void)
-{
-       SBP2_DEBUG("sbp2_init");
-
-       /*
-        * Register our high level driver with 1394 stack
-        */
-       sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops);
-
-       if (sbp2_hl_handle == NULL) {
-               SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
-               return(-ENOMEM);
-       }
-
-       /*
-        * Register our sbp2 status address space...
-        */
-       hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
-                               SBP2_STATUS_FIFO_ADDRESS + 
-                               SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
-
-       /*
-        * Handle data movement if physical dma is not enabled/supported on host controller
-        */
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-       hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
-#endif
-
-       hpsb_register_protocol(&sbp2_driver);
-
-       return 0;
-}
-
-/*
- * This function is called from cleanup module, or during shut-down, in
- * order to unregister our driver.
- */
-void sbp2_cleanup(void)
-{
-       SBP2_DEBUG("sbp2_cleanup");
-
-       hpsb_unregister_protocol(&sbp2_driver);
-
-       if (sbp2_hl_handle) {
-               hpsb_unregister_highlevel(sbp2_hl_handle);
-               sbp2_hl_handle = NULL;
-       }
-}
-
 static int sbp2_probe(struct unit_directory *ud)
 {
        struct sbp2scsi_host_info *hi;
@@ -999,35 +924,44 @@ static void sbp2_add_host(struct hpsb_host *host)
 {
        struct sbp2scsi_host_info *hi;
        unsigned long flags;
+       struct Scsi_Host *scsi_host;
 
        SBP2_DEBUG("sbp2_add_host");
 
-       /* Allocate some memory for our host info structure */
-       hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
-                                                 in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
-
-       if (hi == NULL) {
-               SBP2_ERR("out of memory in sbp2_add_host");
+       /* Register our host with the SCSI stack. */
+       scsi_host = scsi_register (&scsi_driver_template, sizeof(struct sbp2scsi_host_info));
+       if (!scsi_host) {
+               SBP2_ERR("failed to register scsi host");
                return;
        }
 
-       /* Initialize some host stuff */
+       hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata;
        memset(hi, 0, sizeof(struct sbp2scsi_host_info));
+
+       hi->scsi_host = scsi_host;
        INIT_LIST_HEAD(&hi->list);
        hi->host = host;
        hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
+       hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
 
        spin_lock_irqsave(&sbp2_host_info_lock, flags);
        list_add_tail(&hi->list, &sbp2_host_info_list);
        spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
 
-       /* Register our host with the SCSI stack. */
-       hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *));
-       if (hi->scsi_host) {
-               hi->scsi_host->hostdata[0] = (unsigned long)hi;
-               hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
+       /*
+        * XXX(hch): Hopefully the ieee1394 code will be converted
+        * to the driver model at some point.  Until that happens
+        * we'll have to pass in NULL here.
+        */
+       if (scsi_add_host(hi->scsi_host, NULL)) {
+               SBP2_ERR("failed to add scsi host");
+
+               spin_lock_irqsave(&sbp2_host_info_lock, flags);
+               list_del(&hi->list);
+               spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
+
+               scsi_unregister(hi->scsi_host);
        }
-       scsi_driver_template.present++;
 
        return;
 }
@@ -1079,16 +1013,15 @@ static void sbp2_remove_host(struct hpsb_host *host)
        SBP2_DEBUG("sbp2_remove_host");
 
        spin_lock_irqsave(&sbp2_host_info_lock, flags);
-
        hi = sbp2_find_host_info(host);
-       if (hi != NULL) {
+       if (hi)
                list_del(&hi->list);
-               kfree(hi);
-       }
-       else
-               SBP2_ERR("attempt to remove unknown host %p", host);
-
        spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
+
+       if (hi) {
+               scsi_remove_host(hi->scsi_host);
+               scsi_unregister(hi->scsi_host);
+       }
 }
 
 /*
@@ -1098,6 +1031,7 @@ static void sbp2_remove_host(struct hpsb_host *host)
 static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
 {
        struct scsi_id_instance_data *scsi_id = NULL;
+       struct scsi_device *sdev;
        struct node_entry *ne;
        int i;
 
@@ -1203,7 +1137,7 @@ alloc_fail_first:
        /*
         * Find an empty spot to stick our scsi id instance data. 
         */
-       for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
+       for (i = 0; i < hi->scsi_host->max_id; i++) {
                if (!hi->scsi_id[i]) {
                        hi->scsi_id[i] = scsi_id;
                        scsi_id->id = i;
@@ -1224,7 +1158,7 @@ alloc_fail_first:
        /*
         * Make sure we are not out of space
         */
-       if (i == SBP2SCSI_MAX_SCSI_IDS) {
+       if (i == hi->scsi_host->max_id) {
                SBP2_ERR("No slots left for SBP-2 device");
                sbp2_remove_device(hi, scsi_id);
                return -EBUSY;
@@ -1256,6 +1190,13 @@ alloc_fail_first:
         */
        sbp2_max_speed_and_size(hi, scsi_id);
 
+       /* Add this device to the scsi layer now */
+       sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0);
+       if (IS_ERR(sdev)) {
+               SBP2_ERR("scsi_add_device failed");
+               return PTR_ERR(sdev);
+       }
+
        return 0;
 }
 
@@ -1265,13 +1206,21 @@ alloc_fail_first:
 static void sbp2_remove_device(struct sbp2scsi_host_info *hi, 
                               struct scsi_id_instance_data *scsi_id)
 {
+       struct scsi_device *sdev = scsi_find_device(hi->scsi_host, 0, scsi_id->id, 0);
+
        SBP2_DEBUG("sbp2_remove_device");
 
        /* Complete any pending commands with selection timeout */
        sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);
-                               
+
+       /* Remove it from the scsi layer now */
+       if (scsi_remove_device(sdev))
+               SBP2_ERR("scsi_remove_device failed");
+
        sbp2util_remove_command_orb_pool(scsi_id, hi);
 
+       hi->scsi_id[scsi_id->id] = NULL;
+
        if (scsi_id->login_response) {
                pci_free_consistent(hi->host->pdev,
                                    sizeof(struct sbp2_login_response),
@@ -1305,7 +1254,7 @@ static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
        }
 
        SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
-       hi->scsi_id[scsi_id->id] = NULL;
+
        kfree(scsi_id);
 }
 
@@ -1793,8 +1742,8 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
        SBP2_DEBUG("sbp2_max_speed_and_size");
 
        /* Initial setting comes from the hosts speed map */
-       scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64
-                                                 + (scsi_id->ne->nodeid & NODE_MASK)];
+       scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64
+                                                 + NODEID_TO_NODE(scsi_id->ne->nodeid)];
 
        /* Bump down our speed if the user requested it */
        if (scsi_id->speed_code > sbp2_max_speed) {
@@ -2661,7 +2610,7 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        /*
         * Pull our host info and scsi id instance data from the scsi command
         */
-       hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+       hi = (struct sbp2scsi_host_info *) &SCpnt->device->host->hostdata;
 
        if (!hi) {
                SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
@@ -2766,8 +2715,10 @@ static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi,
  *
  * This can be called in interrupt context.
  */
-static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
-                                     Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi,
+                                     struct scsi_id_instance_data *scsi_id,
+                                     u32 scsi_status, Scsi_Cmnd *SCpnt,
+                                     void (*done)(Scsi_Cmnd *))
 {
        unsigned long flags;
 
@@ -2888,7 +2839,7 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
  */
 static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) 
 {
-       struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+       struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata;
        struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
        struct sbp2_command_info *command;
        unsigned long flags;
@@ -2938,7 +2889,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
  */
 static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) 
 {
-       struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+       struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata;
        struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
 
        SBP2_ERR("reset requested");
@@ -2951,93 +2902,81 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
        return(SUCCESS);
 }
 
-/*
- * Called by scsi stack to get bios parameters (used by fdisk, and at boot).
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,43)
-static int sbp2scsi_biosparam (struct scsi_device *sdev,
-                struct block_device *dev, sector_t capacity, int geom[])
+static const char *sbp2scsi_info (struct Scsi_Host *host)
 {
-#else
-static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
+        return "SCSI emulation for for IEEE-1394 Storage Devices";
+}
+
+/* Called for contents of procfs */
+#define SPRINTF(args...) \
+        do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+
+static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset,
+                             int length, int hostno, int inout)
 {
-        unsigned capacity = disk->capacity;
-#endif
-       int heads, sectors, cylinders;
+       Scsi_Device *scd;
+       struct Scsi_Host *host;
+       struct sbp2scsi_host_info *hi;
+       char *pos = buffer;
 
-       SBP2_DEBUG("Request for bios parameters");
+       /* if someone is sending us data, just throw it away */
+       if (inout)
+               return length;
 
-       heads = 64;
-       sectors = 32;
-       cylinders = (int)capacity / (heads * sectors);
+       host = scsi_host_hn_get(hostno);
+       if (!host)  /* if we couldn't find it, we return an error */
+               return -ESRCH;
 
-       if (cylinders > 1024) {
-               heads = 255;
-               sectors = 63;
-               cylinders = (int)capacity / (heads * sectors);
-       }
+       hi = sbp2_find_host_info_scsi(host);
+       if (!hi) /* shouldn't happen, but... */
+               return -ESRCH;
 
-       geom[0] = heads;
-       geom[1] = sectors;
-       geom[2] = cylinders;
+       SPRINTF("Host scsi%d             : SBP-2 IEEE-1394 (%s)\n", hostno,
+               hi->host->driver->name);
+       SPRINTF("Driver version         : %s\n", version);
 
-       return(0);
-}
+       SPRINTF("\nModule options         :\n");
+       SPRINTF("  sbp2_max_speed       : %s\n", hpsb_speedto_str[sbp2_max_speed]);
+       SPRINTF("  sbp2_max_sectors     : %d\n", sbp2_max_sectors);
+       SPRINTF("  sbp2_serialize_io    : %s\n", sbp2_serialize_io ? "yes" : "no");
+       SPRINTF("  sbp2_exclusive_login : %s\n", sbp2_exclusive_login ? "yes" : "no");
 
-/*
- * Called by scsi stack after scsi driver is registered
- */
-static int sbp2scsi_detect (Scsi_Host_Template *tpnt) 
-{
-       SBP2_DEBUG("sbp2scsi_detect");
+       SPRINTF("\nAttached devices       : %s\n", !list_empty(&host->my_devices) ?
+               "" : "none");
 
-       /*
-        * Call sbp2_init to register with the ieee1394 stack. This
-        * results in a callback to sbp2_add_host for each ieee1394
-        * host controller currently registered, and for each of those
-        * we register a scsi host with the scsi stack.
-        */
-       
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       spin_unlock_irq(&io_request_lock);
-       sbp2_init();
-       spin_lock_irq(&io_request_lock);
-#else
-       sbp2_init();
-#endif
+       list_for_each_entry (scd, &host->my_devices, siblings) {
+               int i;
 
-       /* We return the number of hosts registered. */
-       return scsi_driver_template.present;
-}
+               SPRINTF("  [Channel: %02d, Id: %02d, Lun: %02d]  ", scd->channel,
+                       scd->id, scd->lun);
+               SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
+                       scsi_device_types[(short) scd->type] : "Unknown device");
 
+               for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
+                       SPRINTF("%c", scd->vendor[i]);
 
-/*
- * Called for contents of procfs
- */
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
-       struct sbp2scsi_host_info *hi = sbp2_find_host_info_scsi(host);
-       static char info[1024];
+               SPRINTF(" ");
 
-       if (!hi) /* shouldn't happen, but... */
-               return "IEEE-1394 SBP-2 protocol driver";
-
-       sprintf(info, "IEEE-1394 SBP-2 protocol driver (host: %s)\n%s\n"
-               "SBP-2 module load options:\n"
-               "- Max speed supported: %s\n"
-               "- Max sectors per I/O supported: %d\n"
-                "- Serialized I/O (debug): %s\n"
-               "- Exclusive login: %s",
-               hi->host->driver->name,
-               version,
-               hpsb_speedto_str[sbp2_max_speed],
-               sbp2_max_sectors,
-               sbp2_serialize_io ? "yes" : "no",
-               sbp2_exclusive_login ? "yes" : "no");
-
-       return info;
-}
+               for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
+                       SPRINTF("%c", scd->model[i]);
 
+               SPRINTF("\n");
+       }
+
+       SPRINTF("\n");
+
+       /* release the reference count on this host */
+       scsi_host_put(host);
+       /* Calculate start of next buffer, and return value. */
+       *start = buffer + offset;
+
+       if ((pos - buffer) < offset)
+               return (0);
+       else if ((pos - buffer - offset) < length)
+               return (pos - buffer - offset);
+       else
+               return (length);
+}
 
 MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
 MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
@@ -3046,25 +2985,23 @@ MODULE_LICENSE("GPL");
 
 /* SCSI host template */
 static Scsi_Host_Template scsi_driver_template = {
-       .name =                 "IEEE-1394 SBP-2 protocol driver",
-       .info =                 sbp2scsi_info,
-       .detect =               sbp2scsi_detect,
-       .queuecommand =         sbp2scsi_queuecommand,
-       .eh_abort_handler =     sbp2scsi_abort,
-       .eh_device_reset_handler =sbp2scsi_reset,
-       .eh_bus_reset_handler = sbp2scsi_reset,
-       .eh_host_reset_handler =sbp2scsi_reset,
-       .bios_param =           sbp2scsi_biosparam,
-       .this_id =              -1,
-       .sg_tablesize =         SG_ALL,
-       .use_clustering =       ENABLE_CLUSTERING,
-       .cmd_per_lun =          SBP2_MAX_CMDS_PER_LUN,
-       .can_queue =            SBP2_MAX_SCSI_QUEUE,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       .use_new_eh_code =      TRUE,
-#endif
-       .emulated =             1,
-       .proc_name =            SBP2_DEVICE_NAME,
+       .module =                       THIS_MODULE,
+       .name =                         "SBP-2 IEEE-1394",
+       .proc_name =                    SBP2_DEVICE_NAME,
+       .info =                         sbp2scsi_info,
+       .proc_info =                    sbp2scsi_proc_info,
+       .queuecommand =                 sbp2scsi_queuecommand,
+       .eh_abort_handler =             sbp2scsi_abort,
+       .eh_device_reset_handler =      sbp2scsi_reset,
+       .eh_bus_reset_handler =         sbp2scsi_reset,
+       .eh_host_reset_handler =        sbp2scsi_reset,
+       .this_id =                      -1,
+       .sg_tablesize =                 SG_ALL,
+       .use_clustering =               ENABLE_CLUSTERING,
+       .cmd_per_lun =                  SBP2_MAX_CMDS_PER_LUN,
+       .can_queue =                    SBP2_MAX_SCSI_QUEUE,
+       .emulated =                     1,
+       .highmem_io =                   1,
 };
 
 static int sbp2_module_init(void)
@@ -3084,23 +3021,36 @@ static int sbp2_module_init(void)
         */
        scsi_driver_template.max_sectors = sbp2_max_sectors;
 
+
        /*
-        * Ideally we would register our scsi_driver_template with the
-        * scsi stack and after that register with the ieee1394 stack
-        * and process the add_host callbacks. However, the detect
-        * function in the scsi host template requires that we find at
-        * least one host, so we "nest" the registrations by calling
-        * sbp2_init from the detect function.
+        * Register our high level driver with 1394 stack
         */
-       scsi_driver_template.module = THIS_MODULE;
-       if (SCSI_REGISTER_HOST(&scsi_driver_template) ||
-           !scsi_driver_template.present) {
-               SBP2_ERR("Please load the lower level IEEE-1394 driver "
-                        "(e.g. ohci1394) before sbp2...");
-               sbp2_cleanup();
-               return -ENODEV;
+       sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME,
+                                                &sbp2_hl_ops);
+       if (!sbp2_hl_handle) {
+               SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
+               return(-ENOMEM);
        }
 
+       /*
+        * Register our sbp2 status address space...
+        */
+       hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops,
+                               SBP2_STATUS_FIFO_ADDRESS,
+                               SBP2_STATUS_FIFO_ADDRESS + 
+                               SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(
+                                       SBP2SCSI_MAX_SCSI_IDS+1));
+
+       /*
+        * Handle data movement if physical dma is not enabled/supported
+        * on host controller
+        */
+#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+       hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops,
+                       0x0ULL, 0xfffffffcULL);
+#endif
+
+       hpsb_register_protocol(&sbp2_driver);
        return 0;
 }
 
@@ -3108,17 +3058,9 @@ static void __exit sbp2_module_exit(void)
 {
        SBP2_DEBUG("sbp2_module_exit");
 
-       /*
-        * On module unload we unregister with the ieee1394 stack
-        * which results in remove_host callbacks for all ieee1394
-        * host controllers.  In the callbacks we unregister the
-        * corresponding scsi hosts.
-        */
-       sbp2_cleanup();
-
-       if (SCSI_UNREGISTER_HOST(&scsi_driver_template))
-               SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver");
-
+       hpsb_unregister_protocol(&sbp2_driver);
+       if (sbp2_hl_handle)
+               hpsb_unregister_highlevel(sbp2_hl_handle);
 }
 
 module_init(sbp2_module_init);
index 5968d6a3dcc37af9b21a78b608aeac1c95d5d814..8283194b4405058130b039efb498e7e87e62c1f0 100644 (file)
 #ifndef SBP2_H
 #define SBP2_H
 
-/* Some compatibility code */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define SCSI_REGISTER_HOST(tmpl)       scsi_register_module(MODULE_SCSI_HA, tmpl)
-#define SCSI_UNREGISTER_HOST(tmpl)     scsi_unregister_module(MODULE_SCSI_HA, tmpl)
-#else
-#define SCSI_REGISTER_HOST(tmpl)       scsi_register_host(tmpl)
-#define SCSI_UNREGISTER_HOST(tmpl)     scsi_unregister_host(tmpl)
-#endif
-
 #define SBP2_DEVICE_NAME               "sbp2"
 
 /*
@@ -442,8 +433,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
 static void sbp2_add_host(struct hpsb_host *host);
 static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
 static void sbp2_remove_host(struct hpsb_host *host);
-int sbp2_init(void);
-void sbp2_cleanup(void);
 static int sbp2_probe(struct unit_directory *ud);
 static void sbp2_disconnect(struct unit_directory *ud);
 static void sbp2_update(struct unit_directory *ud);
@@ -487,23 +476,4 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
 static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 
-/*
- * Scsi interface related prototypes
- */
-static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
-static const char *sbp2scsi_info (struct Scsi_Host *host);
-void sbp2scsi_setup(char *str, int *ints);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
-static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
-#else
-static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
-#endif
-static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); 
-static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); 
-static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
-                                          u32 status);
-static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
-                                     u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-
 #endif /* SBP2_H */
index 55f288f8b36358a44b8be601d554b41e5e51f683..b616d548b4e85308e197c524cfdd7d3fe9a028ba 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/vmalloc.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -1338,24 +1340,152 @@ MODULE_DESCRIPTION("driver for digital video on OHCI board");
 MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_COMPAT
+
+#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER     \
+       _IOW ('#', 0x12, struct video1394_wait32)
+#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER      \
+       _IOWR('#', 0x13, struct video1394_wait32)
+#define VIDEO1394_IOC32_TALK_WAIT_BUFFER        \
+       _IOW ('#', 0x17, struct video1394_wait32)
+#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER      \
+       _IOWR('#', 0x18, struct video1394_wait32)
+
+struct video1394_wait32 {
+       u32 channel;
+       u32 buffer;
+       struct compat_timeval filltime;
+};
+
+static int video1394_wr_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
+                              struct file *file)
+{
+        struct video1394_wait32 wait32;
+        struct video1394_wait wait;
+        mm_segment_t old_fs;
+        int ret;
+
+       if (file->f_op->ioctl != video1394_ioctl)
+               return -EFAULT;
+
+        if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
+                return -EFAULT;
+
+        wait.channel = wait32.channel;
+        wait.buffer = wait32.buffer;
+        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
+        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
+
+        old_fs = get_fs();
+        set_fs(KERNEL_DS);
+        if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
+               ret = video1394_ioctl(file->f_dentry->d_inode, file,
+                                     VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
+                                     (unsigned long) &wait);
+        else
+               ret = video1394_ioctl(file->f_dentry->d_inode, file,
+                                     VIDEO1394_IOC_LISTEN_POLL_BUFFER,
+                                     (unsigned long) &wait);
+        set_fs(old_fs);
+
+        if (!ret) {
+                wait32.channel = wait.channel;
+                wait32.buffer = wait.buffer;
+                wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
+                wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
+
+                if (copy_to_user((struct video1394_wait32 *)arg, &wait32, sizeof(wait32)))
+                        ret = -EFAULT;
+        }
+
+        return ret;
+}
+
+static int video1394_w_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
+                             struct file *file)
+{
+        struct video1394_wait32 wait32;
+        struct video1394_wait wait;
+        mm_segment_t old_fs;
+        int ret;
+
+       if (file->f_op->ioctl != video1394_ioctl)
+               return -EFAULT;
+
+        if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
+                return -EFAULT;
+
+        wait.channel = wait32.channel;
+        wait.buffer = wait32.buffer;
+        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
+        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
+
+        old_fs = get_fs();
+        set_fs(KERNEL_DS);
+        if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
+               ret = video1394_ioctl(file->f_dentry->d_inode, file,
+                                     VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
+                                     (unsigned long) &wait);
+        else
+               ret = video1394_ioctl(file->f_dentry->d_inode, file,
+                                     VIDEO1394_IOC_TALK_WAIT_BUFFER,
+                                     (unsigned long) &wait);
+        set_fs(old_fs);
+
+        return ret;
+}
+
+static int video1394_queue_buf32(unsigned int fd, unsigned int cmd, unsigned long arg,
+                                struct file *file)
+{
+       if (file->f_op->ioctl != video1394_ioctl)
+               return -EFAULT;
+
+        return -EFAULT;
+
+       return video1394_ioctl(file->f_dentry->d_inode, file,
+                               VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
+}
+
+#endif /* CONFIG_COMPAT */
+
 static void __exit video1394_exit_module (void)
 {
+#ifdef CONFIG_COMPAT
+       int ret;
+
+       ret = unregister_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER);
+       ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER);
+       if (ret)
+               PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations");
+#endif
+
        hpsb_unregister_highlevel (hl_handle);
 
        devfs_unregister(devfs_handle);
        ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
-       
+
        PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
 }
 
 static int __init video1394_init_module (void)
 {
-       if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
-                                     THIS_MODULE, &video1394_fops)) {
+       int ret;
+
+       ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
+                                       THIS_MODULE, &video1394_fops);
+       if (ret) {
                PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
-               return -EIO;
-       }
-       
+               return -EIO;
+        }
+
        devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
 
        hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
@@ -1366,9 +1496,32 @@ static int __init video1394_init_module (void)
                return -ENOMEM;
        }
 
+#ifdef CONFIG_COMPAT
+       /* First the compatible ones */
+       ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL, NULL);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL, NULL);
+
+       /* These need translation */
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER,
+                                   video1394_w_wait32);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER,
+                                   video1394_wr_wait32);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER,
+                                   video1394_queue_buf32);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER,
+                                   video1394_w_wait32);
+       ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER,
+                                   video1394_wr_wait32);
+       if (ret)
+               PRINT_G(KERN_INFO, "Error registering ioctl32 translations");
+#endif
+
        PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
        return 0;
 }
 
+
 module_init(video1394_init_module);
 module_exit(video1394_exit_module);