]> git.hungrycats.org Git - linux/commitdiff
[PATCH] IEEE-1394/Firewire updates
authorBen Collins <bcollins@debian.org>
Thu, 17 Apr 2003 06:07:43 +0000 (23:07 -0700)
committerBen Collins <bcollins@debian.org>
Thu, 17 Apr 2003 06:07:43 +0000 (23:07 -0700)
- Add driver registration for dv1394/video1394/raw1394.
- Fix 3 sleep-while-atomic bugs in ohci1394 and ieee1394.
- Cleanup some bus-reset handling in ohci1394.
- Add empty config-rom handling.
- Check and handle SBP-2 logins active/available for non-exclusive
  logins.
- Fix bug in SBP-2 DMA cleanup.

drivers/ieee1394/dv1394.c
drivers/ieee1394/hosts.c
drivers/ieee1394/ieee1394_hotplug.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 ae5e2a601809d08d5f766026c365672fa9517902..03a9a5d1546fd6c31287212bce741029bcd2c5b6 100644 (file)
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
+#include "ieee1394_hotplug.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h" 
        (will cause undeflows if your machine is too slow!)
 */
 
-#define DV1394_DEBUG_LEVEL 1
+#define DV1394_DEBUG_LEVEL 0
 
 /* for debugging use ONLY: allow more than one open() of the device */
 /* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */
@@ -2469,6 +2470,32 @@ static int dv1394_devfs_add_entry(struct video_card *video)
 }
 #endif /* CONFIG_DEVFS_FS */
 
+
+/*** HOTPLUG STUFF **********************************************************/
+/*
+ * Export information about protocols/devices supported by this driver.
+ */
+static struct ieee1394_device_id dv1394_id_table[] = {
+       {
+               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
+               .version        = AVC_SW_VERSION_ENTRY & 0xffffff
+       },
+       { }
+};
+
+MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
+
+static struct hpsb_protocol_driver dv1394_driver = {
+       .name           = "DV/1394 Driver",
+       .id_table       = dv1394_id_table,
+       .driver         = {
+               .name   = "dv1394",
+               .bus    = &ieee1394_bus_type,
+       },
+};
+
+
 /*** IEEE1394 HPSB CALLBACKS ***********************************************/
 
 static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode)
@@ -2897,6 +2924,8 @@ static void __exit dv1394_exit_module(void)
                printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
 #endif
 
+       hpsb_unregister_protocol(&dv1394_driver);
+
        hpsb_unregister_highlevel (hl_handle);
        ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
@@ -2947,6 +2976,8 @@ static int __init dv1394_init_module(void)
                return -ENOMEM;
        }
 
+       hpsb_register_protocol(&dv1394_driver);
+
 #ifdef CONFIG_COMPAT
        /* First compatible ones */
        ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
index fba9fb09c89f6f2477cb396351c6fab480174b4b..1726629944bce541220fa96a21f5f2c3aba02fa0 100644 (file)
@@ -164,7 +164,7 @@ void hpsb_add_host(struct hpsb_host *host)
         spin_unlock_irqrestore(&hosts_lock, flags);
 
         highlevel_add_host(host);
-        host->driver->devctl(host, RESET_BUS, 0);
+        host->driver->devctl(host, RESET_BUS, LONG_RESET);
 }
 
 void hpsb_remove_host(struct hpsb_host *host)
index 211f9f1721fa089fd1f55c525d2bb351f6c65efd..2720f6a2cebdb74a891412b32cd9f2c83de1ae03 100644 (file)
 #define IEEE1394_MATCH_SPECIFIER_ID    0x0004
 #define IEEE1394_MATCH_VERSION         0x0008
 
+/*
+ * Unit spec id and sw version entry for some protocols
+ */
+#define AVC_UNIT_SPEC_ID_ENTRY                                 0x0000A02D
+#define AVC_SW_VERSION_ENTRY                                   0x00010001
+#define CAMERA_UNIT_SPEC_ID_ENTRY                              0x0000A02D
+#define CAMERA_SW_VERSION_ENTRY                                        0x00000100
+
 struct ieee1394_device_id {
        u32 match_flags;
        u32 vendor_id;
index 73aaaa3243598aff29af807e5367f9bee236489b..de87726d1a639642ce0ebb5c6d5b92d9c8f63696 100644 (file)
@@ -620,6 +620,10 @@ static struct node_entry *nodemgr_scan_root_directory
        
        if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
                return NULL;
+
+       if (CONFIG_ROM_BUS_INFO_LENGTH(quad) == 1)  /* minimal config rom */
+               return NULL;
+
        address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
 
        if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
@@ -1332,6 +1336,13 @@ static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned
        header_size = buffer[0] >> 24;
        addr += 4;
 
+       if (header_size == 1) {
+               HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM.  "
+                         "Vendor is %08x",
+                         NODE_BUS_ARGS(nodeid), buffer[0] & 0x00ffffff);
+               return -1;
+       }
+
        if (header_size < 4) {
                HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM "
                          "format (%d quads), cannot parse",
@@ -1767,6 +1778,7 @@ static void nodemgr_remove_host(struct hpsb_host *host)
                        break;
                }
        }
+       spin_unlock_irqrestore (&host_info_lock, flags);
 
        if (hi) {
                if (hi->pid >= 0) {
@@ -1780,8 +1792,6 @@ static void nodemgr_remove_host(struct hpsb_host *host)
                HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
                         host->driver->name);
 
-       spin_unlock_irqrestore (&host_info_lock, flags);
-
        return;
 }
 
index c1b4693080169d280e4596ac823a9a579741cf8f..c007efd9a2cba8432796d83e2e1696d79b9d7cce 100644 (file)
@@ -995,8 +995,24 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                        return -EFAULT;
                }
 
+               /* activate the legacy IR context */
+               if (ohci->ir_legacy_context.ohci == NULL) {
+                       if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
+                                             DMA_CTX_ISO, 0, IR_NUM_DESC,
+                                             IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
+                                             OHCI1394_IsoRcvContextBase) < 0) {
+                               PRINT(KERN_ERR, ohci->id, "%s: failed to allocate an IR context",
+                                     __FUNCTION__);
+                               return -ENOMEM;
+                       }
+                       ohci->ir_legacy_channels = 0;
+                       initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
+
+                       DBGMSG(ohci->id, "ISO receive legacy context activated");
+               }
+
                mask = (u64)0x1<<arg;
-               
+
                 spin_lock_irqsave(&ohci->IR_channel_lock, flags);
 
                if (ohci->ISO_channel_usage & mask) {
@@ -1007,23 +1023,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                        return -EFAULT;
                }
 
-               /* activate the legacy IR context */
-               if(ohci->ir_legacy_context.ohci == NULL) {
-                       if(alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
-                                            DMA_CTX_ISO, 0, IR_NUM_DESC,
-                                            IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
-                                            OHCI1394_IsoRcvContextBase) < 0) {
-                               PRINT(KERN_ERR, ohci->id,
-                                     "%s: failed to allocate an IR context", 
-                                     __FUNCTION__);
-                               return -ENOMEM;
-                       }
-                       ohci->ir_legacy_channels = 0;
-                       initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
-                       DBGMSG(ohci->id, "ISO receive legacy context activated");
-               }
-
                ohci->ISO_channel_usage |= mask;
                ohci->ir_legacy_channels |= mask;
 
@@ -2318,7 +2317,7 @@ static void ohci_irq_handler(int irq, void *dev_id,
                                 * or out manually into a port! The forced reset seems
                                 * to solve this problem. This mainly effects nForce2. */
                                if (loop_count > 10000) {
-                                       hpsb_reset_bus(host, 1);
+                                       ohci_devctl(host, RESET_BUS, LONG_RESET);
                                        DBGMSG(ohci->id, "Detected bus-reset loop. Forced a bus reset!");
                                        loop_count = 0;
                                }
index 6bbfd38d95db30a7c4d48ba4f70621b8fd56418a..facb0ed0dd146264bd12cdaba46460fdb885b7c3 100644 (file)
@@ -49,6 +49,7 @@
 #include "highlevel.h"
 #include "iso.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_hotplug.h"
 #include "raw1394.h"
 #include "raw1394-private.h"
 
@@ -2474,6 +2475,40 @@ static int raw1394_release(struct inode *inode, struct file *file)
         return 0;
 }
 
+
+/*** HOTPLUG STUFF **********************************************************/
+/*
+ * Export information about protocols/devices supported by this driver.
+ */
+static struct ieee1394_device_id raw1394_id_table[] = {
+       {
+               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
+               .version        = AVC_SW_VERSION_ENTRY & 0xffffff
+       },
+       {
+               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+               .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+               .version        = CAMERA_SW_VERSION_ENTRY & 0xffffff
+       },
+       { }
+};
+
+MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
+
+static struct hpsb_protocol_driver raw1394_driver = {
+       .name           = "raw1394 Driver",
+       .id_table       = raw1394_id_table,
+       .driver         = {
+               .name   = "raw1394",
+               .bus    = &ieee1394_bus_type,
+       },
+};
+
+
+/******************************************************************************/
+
+
 static struct hpsb_highlevel_ops hl_ops = {
         .add_host =    add_host,
         .remove_host = remove_host,
@@ -2515,12 +2550,17 @@ static int __init init_raw1394(void)
                 hpsb_unregister_highlevel(hl_handle);
                 return -EBUSY;
         }
+
         printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME);
+
+       hpsb_register_protocol(&raw1394_driver);
+
         return 0;
 }
 
 static void __exit cleanup_raw1394(void)
 {
+       hpsb_unregister_protocol(&raw1394_driver);
         ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394);
         devfs_unregister(devfs_handle);
         hpsb_unregister_highlevel(hl_handle);
index 1910d0515ac241377bac7a6994c6cc6f75b24f48..f80b2194922e1cd103039f84688a1751e943db85 100644 (file)
@@ -641,7 +641,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
        spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
        for (i = 0; i < orbs; i++) {
                command = (struct sbp2_command_info *)
-                   kmalloc(sizeof(struct sbp2_command_info), GFP_KERNEL);
+                   kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC);
                if (!command) {
                        spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
                        return(-ENOMEM);
@@ -1049,6 +1049,22 @@ static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_director
                goto alloc_fail;
        SBP2_DMA_ALLOC("consistent DMA region for login FIFO");
 
+       /* Query logins ORB DMA */
+       scsi_id->query_logins_orb =
+               pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),
+                                    &scsi_id->query_logins_orb_dma);
+       if (!scsi_id->query_logins_orb)
+               goto alloc_fail;
+       SBP2_DMA_ALLOC("consistent DMA region for query logins ORB");
+
+       /* Query logins response DMA */
+       scsi_id->query_logins_response =
+               pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),
+                                    &scsi_id->query_logins_response_dma);
+       if (!scsi_id->query_logins_response)
+               goto alloc_fail;
+       SBP2_DMA_ALLOC("consistent DMA region for query logins response");
+
        /* Reconnect ORB DMA */
        scsi_id->reconnect_orb =
                pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),
@@ -1071,6 +1087,22 @@ static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_director
                                     &scsi_id->login_orb_dma);
        if (!scsi_id->login_orb) {
 alloc_fail:
+               if (scsi_id->query_logins_response) {
+                       pci_free_consistent(hi->host->pdev,
+                                           sizeof(struct sbp2_query_logins_response),
+                                           scsi_id->query_logins_response,
+                                           scsi_id->query_logins_response_dma);
+                       SBP2_DMA_FREE("query logins response DMA");
+               }
+
+               if (scsi_id->query_logins_orb) {
+                       pci_free_consistent(hi->host->pdev,
+                                           sizeof(struct sbp2_query_logins_orb),
+                                           scsi_id->query_logins_orb,
+                                           scsi_id->query_logins_orb_dma);
+                       SBP2_DMA_FREE("query logins ORB DMA");
+               }
+       
                if (scsi_id->logout_orb) {
                        pci_free_consistent(hi->host->pdev,
                                        sizeof(struct sbp2_logout_orb),
@@ -1241,10 +1273,26 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
                pci_free_consistent(hi->host->pdev,
                                    sizeof(struct sbp2_logout_orb),
                                    scsi_id->logout_orb,
-                                   scsi_id->reconnect_orb_dma);
+                                   scsi_id->logout_orb_dma);
                SBP2_DMA_FREE("single logout orb");
        }
 
+       if (scsi_id->query_logins_orb) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_query_logins_orb),
+                                   scsi_id->query_logins_orb,
+                                   scsi_id->query_logins_orb_dma);
+               SBP2_DMA_FREE("single query logins orb");
+       }
+
+       if (scsi_id->query_logins_response) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_query_logins_response),
+                                   scsi_id->query_logins_response,
+                                   scsi_id->query_logins_response_dma);
+               SBP2_DMA_FREE("single query logins data");
+       }
+
        SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
 
        kfree(scsi_id);
@@ -1299,6 +1347,103 @@ static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
                 (device_type == TYPE_ROM)) ? 1:0);
 }
 
+/*
+ * This function queries the device for the maximum concurrent logins it
+ * supports.
+ */
+static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
+{
+       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       quadlet_t data[2];
+       int max_logins;
+       int active_logins;
+
+       SBP2_DEBUG("sbp2_query_logins");
+
+       scsi_id->query_logins_orb->reserved1 = 0x0;
+       scsi_id->query_logins_orb->reserved2 = 0x0;
+
+       scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;
+       scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized");
+
+       scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(QUERY_LOGINS_REQUEST);
+       scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
+       if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
+               scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+       }
+       SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
+
+       scsi_id->query_logins_orb->reserved_resp_length =
+               ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
+       SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
+
+       scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
+                                                   SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
+       scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
+                                                    SBP2_STATUS_FIFO_ADDRESS_HI);
+       SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
+
+       sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
+
+       SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
+
+       sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(stuct sbp2_query_logins_orb),
+                            "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
+
+       memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
+       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
+
+       SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset");
+
+       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
+       data[1] = scsi_id->query_logins_orb_dma;
+       sbp2util_cpu_to_be32_buffer(data, 8);
+
+       atomic_set(&scsi_id->sbp2_login_complete, 0);
+
+       SBP2_DEBUG("sbp2_query_logins: prepared to write");
+       hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
+       SBP2_DEBUG("sbp2_query_logins: written");
+
+       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
+               SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+               return(-EIO);
+       }
+
+       if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
+               SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+               return(-EIO);
+       }
+
+       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
+           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
+           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
+
+               SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+               return(-EIO);
+       }
+
+       sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));
+
+       SBP2_DEBUG("length_max_logins = %x",
+                  (unsigned int)scsi_id->query_logins_response->length_max_logins);
+
+       SBP2_INFO("Query logins to SBP-2 device successful");
+
+       max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
+       SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
+                                                                                
+       active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
+       SBP2_INFO("Number of active logins: %d", active_logins);
+                                                                                
+       if (active_logins >= max_logins) {
+               return(-EIO);
+       }
+                                                                                
+       return 0;
+}
+
 /*
  * This function is called in order to login to a particular SBP-2 device,
  * after a bus reset.
@@ -1315,6 +1460,13 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
                return(-EIO);
        }
 
+       if (!exclusive_login) {
+               if (sbp2_query_logins(scsi_id)) {
+                       SBP2_ERR("Device does not support any more concurrent logins");
+                       return(-EIO);
+               }
+       }
+
        /* Set-up login ORB, assume no password */
        scsi_id->login_orb->password_hi = 0; 
        scsi_id->login_orb->password_lo = 0;
@@ -2563,6 +2715,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                 * It's probably a login/logout/reconnect status.
                 */
                if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
+                   (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
                    (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
                    (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) {
                        atomic_set(&scsi_id->sbp2_login_complete, 1);
index d56fc82d9ecb16803e453e22120cb71afec171f7..a642dcf3c17dfadb4d5a7a9d86d8608fddcab107 100644 (file)
@@ -93,6 +93,29 @@ struct sbp2_login_response {
 
 #define ORB_SET_LOGIN_ID(value)                 (value & 0xffff)
 
+#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff)
+
+struct sbp2_query_logins_orb {
+       u32 reserved1;
+       u32 reserved2;
+       u32 query_response_hi;
+       u32 query_response_lo;
+       u32 lun_misc;
+       u32 reserved_resp_length;
+       u32 status_FIFO_hi;
+       u32 status_FIFO_lo;
+};
+
+#define RESPONSE_GET_MAX_LOGINS(value)          (value & 0xffff)
+#define RESPONSE_GET_ACTIVE_LOGINS(value)       ((RESPONSE_GET_LENGTH(value) - 4) / 12)
+
+struct sbp2_query_logins_response {
+       u32 length_max_logins;
+       u32 misc_IDs;
+       u32 initiator_misc_hi;
+       u32 initiator_misc_lo;
+};
+
 struct sbp2_reconnect_orb {
        u32 reserved1;
        u32 reserved2;
@@ -340,6 +363,10 @@ struct scsi_id_instance_data {
        dma_addr_t login_orb_dma;
        struct sbp2_login_response *login_response;
        dma_addr_t login_response_dma;
+       struct sbp2_query_logins_orb *query_logins_orb;
+       dma_addr_t query_logins_orb_dma;
+       struct sbp2_query_logins_response *query_logins_response;
+       dma_addr_t query_logins_response_dma;
        struct sbp2_reconnect_orb *reconnect_orb;
        dma_addr_t reconnect_orb_dma;
        struct sbp2_logout_orb *logout_orb;
@@ -365,7 +392,7 @@ struct scsi_id_instance_data {
        u32 sbp2_firmware_revision;
 
        /* 
-        * Variable used for logins, reconnects, logouts 
+        * Variable used for logins, reconnects, logouts, query logins
         */
        atomic_t sbp2_login_complete;
 
@@ -457,6 +484,7 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_
 /*
  * SBP-2 protocol related prototypes
  */
+static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id);
 static int sbp2_login_device(struct scsi_id_instance_data *scsi_id);
 static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id); 
 static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id); 
index 3cca2fbbd5298c770781b0d29021003f6c934b2a..50988d1d7ff89e7f6bfc6d9ca2b291639b7d2442 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
+#include "ieee1394_hotplug.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h"
@@ -1247,6 +1248,31 @@ static struct file_operations video1394_fops=
        .release =      video1394_release
 };
 
+/*** HOTPLUG STUFF **********************************************************/
+/*
+ * Export information about protocols/devices supported by this driver.
+ */
+static struct ieee1394_device_id video1394_id_table[] = {
+       {
+               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+               .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+               .version        = CAMERA_SW_VERSION_ENTRY & 0xffffff
+       },
+       { }
+};
+
+MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
+
+static struct hpsb_protocol_driver video1394_driver = {
+       .name           = "1394 Digital Camera Driver",
+       .id_table       = video1394_id_table,
+       .driver         = {
+               .name   = VIDEO1394_DRIVER_NAME,
+               .bus    = &ieee1394_bus_type,
+       },
+};
+
+
 static int video1394_init(struct ti_ohci *ohci)
 {
        struct video_card *video;
@@ -1467,6 +1493,8 @@ static void __exit video1394_exit_module (void)
                PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations");
 #endif
 
+       hpsb_unregister_protocol(&video1394_driver);
+
        hpsb_unregister_highlevel (hl_handle);
 
        devfs_unregister(devfs_handle);
@@ -1496,6 +1524,8 @@ static int __init video1394_init_module (void)
                return -ENOMEM;
        }
 
+       hpsb_register_protocol(&video1394_driver);
+
 #ifdef CONFIG_COMPAT
        /* First the compatible ones */
        ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL);