00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
#include <linux/version.h>
00026
#include <linux/kernel.h>
00027
#include <linux/module.h>
00028
#include <linux/pci.h>
00029
#include <linux/pci_ids.h>
00030
00031 int smiReset = 0;
00032
MODULE_PARM(smiReset,
"i");
00033
00034
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00035
#define pci_get_device(a, b, c) pci_find_device(a, b, c)
00036
#define pci_dev_put(a) do { } while(0)
00037
#endif
00038
00039
00040 #define CONFIG_RTAI_HW_SMI_ALL 0
00041 #define CONFIG_RTAI_HW_SMI_INTEL_USB2 0
00042 #define CONFIG_RTAI_HW_SMI_LEGACY_USB2 0
00043 #define CONFIG_RTAI_HW_SMI_PERIODIC 0
00044 #define CONFIG_RTAI_HW_SMI_TCO 0
00045 #define CONFIG_RTAI_HW_SMI_MC 0
00046 #define CONFIG_RTAI_HW_SMI_APMC 0
00047 #define CONFIG_RTAI_HW_SMI_LEGACY_USB 0
00048 #define CONFIG_RTAI_HW_SMI_BIOS 0
00049
00050 static struct pci_device_id rthal_smi_pci_tbl[]
__initdata = {
00051 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0) },
00052 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0) },
00053 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0) },
00054 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10) },
00055 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0) },
00056 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0) },
00057 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12) },
00058 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0) },
00059 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12) },
00060 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0) },
00061 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0) },
00062 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1) },
00063 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2) },
00064 { 0, },
00065 };
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define DEVFN 0xf8
00076
00077 #define PMBASE_B0 0x40
00078 #define PMBASE_B1 0x41
00079
00080 #define SMI_CTRL_ADDR 0x30
00081 #define SMI_STATUS_ADDR 0x34
00082 #define SMI_MON_ADDR 0x40
00083
00084
00085 #define INTEL_USB2_EN_BIT (0x01 << 18)
00086 #define LEGACY_USB2_EN_BIT (0x01 << 17)
00087 #define PERIODIC_EN_BIT (0x01 << 14)
00088 #define TCO_EN_BIT (0x01 << 13)
00089 #define MCSMI_EN_BIT (0x01 << 11)
00090 #define SWSMI_TMR_EN_BIT (0x01 << 6)
00091 #define APMC_EN_BIT (0x01 << 5)
00092 #define SLP_EN_BIT (0x01 << 4)
00093 #define LEGACY_USB_EN_BIT (0x01 << 3)
00094 #define BIOS_EN_BIT (0x01 << 2)
00095 #define GBL_SMI_EN_BIT (0x01)
00096
00097 static const unsigned rthal_smi_masked_bits = 0
00098
#if CONFIG_RTAI_HW_SMI_ALL
00099
|
GBL_SMI_EN_BIT
00100
#else
00101
#if CONFIG_RTAI_HW_SMI_INTEL_USB2
00102
|
INTEL_USB2_EN_BIT
00103
#endif
00104
#if CONFIG_RTAI_HW_SMI_LEGACY_USB2
00105
|
LEGACY_USB2_EN_BIT
00106
#endif
00107
#if CONFIG_RTAI_HW_SMI_PERIODIC
00108
|
PERIODIC_EN_BIT
00109
#endif
00110
#if CONFIG_RTAI_HW_SMI_TCO
00111
|
TCO_EN_BIT
00112
#endif
00113
#if CONFIG_RTAI_HW_SMI_MC
00114
|
MCSMI_EN_BIT
00115
#endif
00116
#if CONFIG_RTAI_HW_SMI_APMC
00117
|
APMC_EN_BIT
00118
#endif
00119
#if CONFIG_RTAI_HW_SMI_LEGACY_USB
00120
|
LEGACY_USB_EN_BIT
00121
#endif
00122
#if CONFIG_RTAI_HW_SMI_BIOS
00123
|
BIOS_EN_BIT
00124
#endif
00125
#endif
00126
;
00127
00128 static unsigned rthal_smi_saved_bits;
00129 static unsigned short rthal_smi_en_addr;
00130 static struct pci_dev *
smi_dev;
00131
00132 #define mask_bits(v, p) outl(inl(p) & ~(v), (p))
00133 #define set_bits(v, p) outl(inl(p) | (v), (p))
00134
00135 void rthal_smi_restore(
void)
00136 {
00137
if (
rthal_smi_en_addr) {
00138
set_bits(
rthal_smi_saved_bits,
rthal_smi_en_addr);
00139 pci_dev_put(
smi_dev);
00140 }
00141 }
00142
00143 void rthal_smi_disable(
void)
00144 {
00145
if (
rthal_smi_en_addr) {
00146
rthal_smi_saved_bits = inl(
rthal_smi_en_addr) &
rthal_smi_masked_bits;
00147
mask_bits(
rthal_smi_masked_bits,
rthal_smi_en_addr);
00148 }
00149 }
00150
00151 static unsigned short __devinit
get_smi_en_addr(
struct pci_dev *dev)
00152 {
00153 u_int8_t byte0, byte1;
00154
00155 pci_read_config_byte (dev,
PMBASE_B0, &byte0);
00156 pci_read_config_byte (dev,
PMBASE_B1, &byte1);
00157
return SMI_CTRL_ADDR + (((byte1 << 1) | (byte0 >> 7)) << 7);
00158 }
00159
00160 int __devinit
rthal_smi_init(
void)
00161 {
00162
struct pci_dev *dev = NULL;
00163
struct pci_device_id *
id;
00164
00165
00166
00167
00168
00169
for (
id = &rthal_smi_pci_tbl[0]; dev == NULL &&
id->vendor != 0;
id++) {
00170 dev = pci_get_device(id->vendor, id->device, NULL);
00171 }
00172
00173
if (dev == NULL || dev->bus->number || dev->devfn !=
DEVFN) {
00174 pci_dev_put(dev);
00175
printk(
"RTAI: Intel chipset not found.\n");
00176
return -ENODEV;
00177 }
00178
00179
printk(
"RTAI: Intel chipset found, enabling SMI workaround.\n");
00180
rthal_smi_en_addr =
get_smi_en_addr(dev);
00181
smi_dev = dev;
00182
return 0;
00183 }
00184
00185
00186 int init_module(
void)
00187 {
00188
int retval;
00189
if (!(retval =
rthal_smi_init())) {
00190
printk(
"SMI module loaded\n");
00191 }
00192
return retval;
00193 }
00194
00195 void cleanup_module(
void)
00196 {
00197
if (
smiReset) {
00198
rthal_smi_restore();
00199
printk(
"SMI module unloaded and reset\n");
00200 }
else {
00201
printk(
"SMI module unloaded but not reset\n");
00202 }
00203 }
00204
00205
MODULE_LICENSE(
"GPL");
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252