0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014 #include <linux/pci.h>
0015 #include <linux/pci_hotplug.h>
0016 #include <linux/proc_fs.h>
0017 #include "../pci.h"
0018 #include "cpci_hotplug.h"
0019
0020 #define MY_NAME "cpci_hotplug"
0021
0022 #define dbg(format, arg...) \
0023 do { \
0024 if (cpci_debug) \
0025 printk(KERN_DEBUG "%s: " format "\n", \
0026 MY_NAME, ## arg); \
0027 } while (0)
0028 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
0029 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
0030 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
0031
0032
0033 u8 cpci_get_attention_status(struct slot *slot)
0034 {
0035 int hs_cap;
0036 u16 hs_csr;
0037
0038 hs_cap = pci_bus_find_capability(slot->bus,
0039 slot->devfn,
0040 PCI_CAP_ID_CHSWP);
0041 if (!hs_cap)
0042 return 0;
0043
0044 if (pci_bus_read_config_word(slot->bus,
0045 slot->devfn,
0046 hs_cap + 2,
0047 &hs_csr))
0048 return 0;
0049
0050 return hs_csr & 0x0008 ? 1 : 0;
0051 }
0052
0053 int cpci_set_attention_status(struct slot *slot, int status)
0054 {
0055 int hs_cap;
0056 u16 hs_csr;
0057
0058 hs_cap = pci_bus_find_capability(slot->bus,
0059 slot->devfn,
0060 PCI_CAP_ID_CHSWP);
0061 if (!hs_cap)
0062 return 0;
0063 if (pci_bus_read_config_word(slot->bus,
0064 slot->devfn,
0065 hs_cap + 2,
0066 &hs_csr))
0067 return 0;
0068 if (status)
0069 hs_csr |= HS_CSR_LOO;
0070 else
0071 hs_csr &= ~HS_CSR_LOO;
0072 if (pci_bus_write_config_word(slot->bus,
0073 slot->devfn,
0074 hs_cap + 2,
0075 hs_csr))
0076 return 0;
0077 return 1;
0078 }
0079
0080 u16 cpci_get_hs_csr(struct slot *slot)
0081 {
0082 int hs_cap;
0083 u16 hs_csr;
0084
0085 hs_cap = pci_bus_find_capability(slot->bus,
0086 slot->devfn,
0087 PCI_CAP_ID_CHSWP);
0088 if (!hs_cap)
0089 return 0xFFFF;
0090 if (pci_bus_read_config_word(slot->bus,
0091 slot->devfn,
0092 hs_cap + 2,
0093 &hs_csr))
0094 return 0xFFFF;
0095 return hs_csr;
0096 }
0097
0098 int cpci_check_and_clear_ins(struct slot *slot)
0099 {
0100 int hs_cap;
0101 u16 hs_csr;
0102 int ins = 0;
0103
0104 hs_cap = pci_bus_find_capability(slot->bus,
0105 slot->devfn,
0106 PCI_CAP_ID_CHSWP);
0107 if (!hs_cap)
0108 return 0;
0109 if (pci_bus_read_config_word(slot->bus,
0110 slot->devfn,
0111 hs_cap + 2,
0112 &hs_csr))
0113 return 0;
0114 if (hs_csr & HS_CSR_INS) {
0115
0116 if (pci_bus_write_config_word(slot->bus,
0117 slot->devfn,
0118 hs_cap + 2,
0119 hs_csr))
0120 ins = 0;
0121 else
0122 ins = 1;
0123 }
0124 return ins;
0125 }
0126
0127 int cpci_check_ext(struct slot *slot)
0128 {
0129 int hs_cap;
0130 u16 hs_csr;
0131 int ext = 0;
0132
0133 hs_cap = pci_bus_find_capability(slot->bus,
0134 slot->devfn,
0135 PCI_CAP_ID_CHSWP);
0136 if (!hs_cap)
0137 return 0;
0138 if (pci_bus_read_config_word(slot->bus,
0139 slot->devfn,
0140 hs_cap + 2,
0141 &hs_csr))
0142 return 0;
0143 if (hs_csr & HS_CSR_EXT)
0144 ext = 1;
0145 return ext;
0146 }
0147
0148 int cpci_clear_ext(struct slot *slot)
0149 {
0150 int hs_cap;
0151 u16 hs_csr;
0152
0153 hs_cap = pci_bus_find_capability(slot->bus,
0154 slot->devfn,
0155 PCI_CAP_ID_CHSWP);
0156 if (!hs_cap)
0157 return -ENODEV;
0158 if (pci_bus_read_config_word(slot->bus,
0159 slot->devfn,
0160 hs_cap + 2,
0161 &hs_csr))
0162 return -ENODEV;
0163 if (hs_csr & HS_CSR_EXT) {
0164
0165 if (pci_bus_write_config_word(slot->bus,
0166 slot->devfn,
0167 hs_cap + 2,
0168 hs_csr))
0169 return -ENODEV;
0170 }
0171 return 0;
0172 }
0173
0174 int cpci_led_on(struct slot *slot)
0175 {
0176 int hs_cap;
0177 u16 hs_csr;
0178
0179 hs_cap = pci_bus_find_capability(slot->bus,
0180 slot->devfn,
0181 PCI_CAP_ID_CHSWP);
0182 if (!hs_cap)
0183 return -ENODEV;
0184 if (pci_bus_read_config_word(slot->bus,
0185 slot->devfn,
0186 hs_cap + 2,
0187 &hs_csr))
0188 return -ENODEV;
0189 if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
0190 hs_csr |= HS_CSR_LOO;
0191 if (pci_bus_write_config_word(slot->bus,
0192 slot->devfn,
0193 hs_cap + 2,
0194 hs_csr)) {
0195 err("Could not set LOO for slot %s", slot_name(slot));
0196 return -ENODEV;
0197 }
0198 }
0199 return 0;
0200 }
0201
0202 int cpci_led_off(struct slot *slot)
0203 {
0204 int hs_cap;
0205 u16 hs_csr;
0206
0207 hs_cap = pci_bus_find_capability(slot->bus,
0208 slot->devfn,
0209 PCI_CAP_ID_CHSWP);
0210 if (!hs_cap)
0211 return -ENODEV;
0212 if (pci_bus_read_config_word(slot->bus,
0213 slot->devfn,
0214 hs_cap + 2,
0215 &hs_csr))
0216 return -ENODEV;
0217 if (hs_csr & HS_CSR_LOO) {
0218 hs_csr &= ~HS_CSR_LOO;
0219 if (pci_bus_write_config_word(slot->bus,
0220 slot->devfn,
0221 hs_cap + 2,
0222 hs_csr)) {
0223 err("Could not clear LOO for slot %s", slot_name(slot));
0224 return -ENODEV;
0225 }
0226 }
0227 return 0;
0228 }
0229
0230
0231
0232
0233
0234
0235 int cpci_configure_slot(struct slot *slot)
0236 {
0237 struct pci_dev *dev;
0238 struct pci_bus *parent;
0239 int ret = 0;
0240
0241 dbg("%s - enter", __func__);
0242
0243 pci_lock_rescan_remove();
0244
0245 if (slot->dev == NULL) {
0246 dbg("pci_dev null, finding %02x:%02x:%x",
0247 slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
0248 slot->dev = pci_get_slot(slot->bus, slot->devfn);
0249 }
0250
0251
0252 if (slot->dev == NULL) {
0253 int n;
0254 dbg("pci_dev still null");
0255
0256
0257
0258
0259
0260 n = pci_scan_slot(slot->bus, slot->devfn);
0261 dbg("%s: pci_scan_slot returned %d", __func__, n);
0262 slot->dev = pci_get_slot(slot->bus, slot->devfn);
0263 if (slot->dev == NULL) {
0264 err("Could not find PCI device for slot %02x", slot->number);
0265 ret = -ENODEV;
0266 goto out;
0267 }
0268 }
0269 parent = slot->dev->bus;
0270
0271 for_each_pci_bridge(dev, parent) {
0272 if (PCI_SLOT(dev->devfn) == PCI_SLOT(slot->devfn))
0273 pci_hp_add_bridge(dev);
0274 }
0275
0276 pci_assign_unassigned_bridge_resources(parent->self);
0277
0278 pci_bus_add_devices(parent);
0279
0280 out:
0281 pci_unlock_rescan_remove();
0282 dbg("%s - exit", __func__);
0283 return ret;
0284 }
0285
0286 int cpci_unconfigure_slot(struct slot *slot)
0287 {
0288 struct pci_dev *dev, *temp;
0289
0290 dbg("%s - enter", __func__);
0291 if (!slot->dev) {
0292 err("No device for slot %02x\n", slot->number);
0293 return -ENODEV;
0294 }
0295
0296 pci_lock_rescan_remove();
0297
0298 list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
0299 if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
0300 continue;
0301 pci_dev_get(dev);
0302 pci_stop_and_remove_bus_device(dev);
0303 pci_dev_put(dev);
0304 }
0305 pci_dev_put(slot->dev);
0306 slot->dev = NULL;
0307
0308 pci_unlock_rescan_remove();
0309
0310 dbg("%s - exit", __func__);
0311 return 0;
0312 }