From d79d8cc679f9b1053acb001e285e39eb44046261 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Mon, 3 Mar 2003 18:55:45 -0800 Subject: [PATCH] [PATCH] IEEE1394 updates - 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. --- drivers/ieee1394/amdtp.c | 29 +- drivers/ieee1394/dma.c | 1 + drivers/ieee1394/dv1394.c | 137 +++++++- drivers/ieee1394/eth1394.c | 266 +++++++++++++-- drivers/ieee1394/eth1394.h | 13 + drivers/ieee1394/hosts.c | 3 - drivers/ieee1394/ieee1394-ioctl.h | 6 +- drivers/ieee1394/ieee1394_core.c | 14 +- drivers/ieee1394/ieee1394_transactions.c | 67 +++- drivers/ieee1394/ieee1394_transactions.h | 3 + drivers/ieee1394/ieee1394_types.h | 9 +- drivers/ieee1394/nodemgr.c | 57 +++- drivers/ieee1394/ohci1394.c | 109 +++--- drivers/ieee1394/raw1394.c | 9 +- drivers/ieee1394/sbp2.c | 412 ++++++++++------------- drivers/ieee1394/sbp2.h | 30 -- drivers/ieee1394/video1394.c | 165 ++++++++- 17 files changed, 956 insertions(+), 374 deletions(-) diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 0b382a2af0e70..6e7b20f898c30 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -74,6 +74,8 @@ #include #include #include +#include +#include #include #include @@ -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); diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index eff68419f5fc4..9ef4dbfc942c7 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "dma.h" /* dma_prog_region */ diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9e1252f34a598..09b0a29c62b34 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -111,6 +111,8 @@ #include #include #include +#include +#include #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); - diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 9aadf74fdefc5..32b2e0c5f688e 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -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 "; + "$Rev: 801 $ Ben Collins "; /* 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); } diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index 44c1637182c6a..1c38fb02cdfe8 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -30,9 +30,16 @@ #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 */ diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index f6669023152b7..fba9fb09c89f6 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -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; } diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h index d9d99bc2706c7..1091bdff1391f 100644 --- a/drivers/ieee1394/ieee1394-ioctl.h +++ b/drivers/ieee1394/ieee1394-ioctl.h @@ -4,8 +4,8 @@ #ifndef __IEEE1394_IOCTL_H #define __IEEE1394_IOCTL_H -#include -#include +#include +#include /* 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 \ diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 35b5571efd045..ea7c5c189d142 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -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 **/ diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 8802070a3d612..7b5a6af229687 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -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; +} diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h index 3750e40c0bc7a..5cbcec56b82d5 100644 --- a/drivers/ieee1394/ieee1394_transactions.h +++ b/drivers/ieee1394/ieee1394_transactions.h @@ -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 */ diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index 691705cd12869..95b8965bb2bd1 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -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) diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 970aa1e09de65..72412bcfe1d57 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -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 diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index ea268b5b071bb..9da0dce7b83fe 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -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 "; + "$Rev: 801 $ Ben Collins "; /* 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, }, diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index e93bc36a77ef4..6bbfd38d95db3 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -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; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index e5631a8268c47..dbeb597a683e7 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -27,30 +27,6 @@ * 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: @@ -136,14 +112,6 @@ * - 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: * @@ -295,10 +263,11 @@ * 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 * 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) * */ @@ -350,7 +319,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 779 $ James Goodwin "; + "$Rev: 797 $ James Goodwin "; /* * 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 "); 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); diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 5968d6a3dcc37..8283194b44050 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -22,15 +22,6 @@ #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 */ diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 55f288f8b3635..b616d548b4e85 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #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); -- 2.53.0