]> xenbits.xensource.com Git - xenclient/ioemu.git/commitdiff
Workaround to support HP/Lenovo WLAN cards.
authorRoss Philipson <rossp@latara.uk.xensource.com>
Mon, 10 Nov 2008 14:31:23 +0000 (14:31 +0000)
committerRoss Philipson <rossp@latara.uk.xensource.com>
Mon, 10 Nov 2008 14:31:23 +0000 (14:31 +0000)
Modified the PCI emulation code to allow the Device ID and
Subsystem ID to be changed for HP/Lenovo WLAN cards to allow
them to be passed through.

Committer: Ross Philipson <ross.philipson@citrix.com>

On branch wlanpt
Changes to be committed:
   modified:   hw/pass-through.c

hw/pass-through.c

index a3b8319d7fcd66bfac6b9f5a52e706d76b398746..253b3c1abc68114f92d015b407d79fa4de4e458f 100644 (file)
@@ -49,6 +49,10 @@ struct dpci_infos {
 /* prototype */
 static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_deviceid_reg_init(struct pt_dev *ptdev,
+    struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_subsystemid_reg_init(struct pt_dev *ptdev,
+    struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_status_reg_init(struct pt_dev *ptdev,
@@ -153,6 +157,17 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev,
  
 /* Header Type0 reg static infomation table */
 static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = {
+    /* Device ID reg */
+    {
+        .offset     = PCI_DEVICE_ID,
+        .size       = 2,
+        .init_val   = 0x0000,
+        .ro_mask    = 0xFFFF,
+        .emu_mask   = 0xFFFF,
+        .init       = pt_deviceid_reg_init,
+        .u.w.read   = pt_word_reg_read,
+        .u.w.write  = pt_word_reg_write,
+    },
     /* Command reg */
     {
         .offset     = PCI_COMMAND,
@@ -299,6 +314,17 @@ static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = {
         .u.dw.read  = pt_bar_reg_read,
         .u.dw.write = pt_bar_reg_write,
     },
+    /* Subsystem ID reg */
+    {
+        .offset     = PCI_SUBSYSTEM_ID,
+        .size       = 2,
+        .init_val   = 0x0000,
+        .ro_mask    = 0xFFFF,
+        .emu_mask   = 0xFFFF,
+        .init       = pt_subsystemid_reg_init,
+        .u.w.read   = pt_word_reg_read,
+        .u.w.write  = pt_word_reg_write,
+    },
     /* Expansion ROM BAR reg */
     {
         .offset     = PCI_ROM_ADDRESS,
@@ -1762,6 +1788,64 @@ static uint32_t pt_common_reg_init(struct pt_dev *ptdev,
     return reg->init_val;
 }
 
+/* platform specific helper for identifying Intel WLAN cards */
+static int pt_wlan_device_check(uint32_t vendor_id, uint32_t device_id)
+{
+    if (vendor_id == 0x8086)
+    {
+           switch (device_id) {
+           case 0x4227:
+           case 0x4230:
+           case 0x4233:
+           case 0x4236:
+           case 0x4237:
+           case 0x423B:
+           case 0x423D:
+               return 1;
+           }
+    }
+    return 0;
+}
+
+/* initialize Device ID register value */
+static uint32_t pt_deviceid_reg_init(struct pt_dev *ptdev,
+        struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+    struct pci_dev *pci_dev = ptdev->pci_dev;
+    uint32_t val;
+
+    /* read the Vendor and Device IDs, set the Device ID for default case */
+    val = pci_read_long(pci_dev, PCI_VENDOR_ID);
+    reg->init_val = ((val >> 16) & 0x0000FFFF);
+
+    /* Intel WLAN device filtering */
+    if (pt_wlan_device_check((val & 0x0000FFFF), ((val >> 16) & 0x0000FFFF)))
+        reg->init_val = 0x4235; /* reset Device ID to one that does not cause the OEM auth checks */           
+
+    return reg->init_val;
+}
+
+/* initialize Sybsystem ID register value */
+static uint32_t pt_subsystemid_reg_init(struct pt_dev *ptdev,
+        struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+    struct pci_dev *pci_dev = ptdev->pci_dev;
+    uint32_t val;
+
+    /* set the Subsystem ID for default case */
+    val = pci_read_word(pci_dev, PCI_SUBSYSTEM_ID);
+    reg->init_val = (val & 0x0000FFFF);
+
+    /* read the Vendor and Device IDs */
+    val = pci_read_long(pci_dev, PCI_VENDOR_ID);
+
+    /* Intel WLAN device filtering */
+    if (pt_wlan_device_check((val & 0x0000FFFF), ((val >> 16) & 0x0000FFFF)))
+        reg->init_val = 0x1001; /* reset Subsystem ID to one that does not cause the OEM auth checks */                
+
+    return reg->init_val;
+}
+
 /* initialize Capabilities Pointer or Next Pointer register */
 static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,
         struct pt_reg_info_tbl *reg, uint32_t real_offset)