0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0037
0038 #include <linux/interrupt.h>
0039 #include <linux/module.h>
0040 #include <linux/moduleparam.h>
0041 #include <linux/types.h>
0042 #include <linux/miscdevice.h>
0043 #include <linux/watchdog.h>
0044 #include <linux/ioport.h>
0045 #include <linux/delay.h>
0046 #include <linux/notifier.h>
0047 #include <linux/reboot.h>
0048 #include <linux/fs.h>
0049 #include <linux/pci.h>
0050 #include <linux/io.h>
0051 #include <linux/uaccess.h>
0052
0053
0054 #define WDT_IS_PCI
0055 #include "wd501p.h"
0056
0057
0058 static int dev_count;
0059
0060 static unsigned long open_lock;
0061 static DEFINE_SPINLOCK(wdtpci_lock);
0062 static char expect_close;
0063
0064 static resource_size_t io;
0065 static int irq;
0066
0067
0068 #define WD_TIMO 60
0069
0070 static int heartbeat = WD_TIMO;
0071 static int wd_heartbeat;
0072 module_param(heartbeat, int, 0);
0073 MODULE_PARM_DESC(heartbeat,
0074 "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
0075 __MODULE_STRING(WD_TIMO) ")");
0076
0077 static bool nowayout = WATCHDOG_NOWAYOUT;
0078 module_param(nowayout, bool, 0);
0079 MODULE_PARM_DESC(nowayout,
0080 "Watchdog cannot be stopped once started (default="
0081 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0082
0083
0084 static int tachometer;
0085 module_param(tachometer, int, 0);
0086 MODULE_PARM_DESC(tachometer,
0087 "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
0088
0089 static int type = 500;
0090 module_param(type, int, 0);
0091 MODULE_PARM_DESC(type,
0092 "PCI-WDT501 Card type (500 or 501 , default=500)");
0093
0094
0095
0096
0097
0098 static void wdtpci_ctr_mode(int ctr, int mode)
0099 {
0100 ctr <<= 6;
0101 ctr |= 0x30;
0102 ctr |= (mode << 1);
0103 outb(ctr, WDT_CR);
0104 udelay(8);
0105 }
0106
0107 static void wdtpci_ctr_load(int ctr, int val)
0108 {
0109 outb(val & 0xFF, WDT_COUNT0 + ctr);
0110 udelay(8);
0111 outb(val >> 8, WDT_COUNT0 + ctr);
0112 udelay(8);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121 static int wdtpci_start(void)
0122 {
0123 unsigned long flags;
0124
0125 spin_lock_irqsave(&wdtpci_lock, flags);
0126
0127
0128
0129
0130
0131 inb(WDT_DC);
0132 udelay(8);
0133 wdtpci_ctr_mode(2, 0);
0134
0135 outb(0, WDT_DC);
0136 udelay(8);
0137 inb(WDT_DC);
0138 udelay(8);
0139 outb(0, WDT_CLOCK);
0140 udelay(8);
0141 inb(WDT_BUZZER);
0142 udelay(8);
0143 inb(WDT_OPTONOTRST);
0144 udelay(8);
0145 inb(WDT_OPTORST);
0146 udelay(8);
0147 inb(WDT_PROGOUT);
0148 udelay(8);
0149 wdtpci_ctr_mode(0, 3);
0150
0151 wdtpci_ctr_mode(1, 2);
0152
0153 wdtpci_ctr_mode(2, 1);
0154
0155 wdtpci_ctr_load(0, 20833);
0156 wdtpci_ctr_load(1, wd_heartbeat);
0157
0158 outb(0, WDT_DC);
0159 udelay(8);
0160
0161 spin_unlock_irqrestore(&wdtpci_lock, flags);
0162 return 0;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171 static int wdtpci_stop(void)
0172 {
0173 unsigned long flags;
0174
0175
0176 spin_lock_irqsave(&wdtpci_lock, flags);
0177 inb(WDT_DC);
0178 udelay(8);
0179 wdtpci_ctr_load(2, 0);
0180 spin_unlock_irqrestore(&wdtpci_lock, flags);
0181 return 0;
0182 }
0183
0184
0185
0186
0187
0188
0189
0190
0191 static int wdtpci_ping(void)
0192 {
0193 unsigned long flags;
0194
0195 spin_lock_irqsave(&wdtpci_lock, flags);
0196
0197 inb(WDT_DC);
0198 udelay(8);
0199 wdtpci_ctr_mode(1, 2);
0200
0201 wdtpci_ctr_load(1, wd_heartbeat);
0202 outb(0, WDT_DC);
0203 udelay(8);
0204 spin_unlock_irqrestore(&wdtpci_lock, flags);
0205 return 0;
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 static int wdtpci_set_heartbeat(int t)
0217 {
0218
0219 if (t < 1 || t > 65535)
0220 return -EINVAL;
0221
0222 heartbeat = t;
0223 wd_heartbeat = t * 100;
0224 return 0;
0225 }
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 static int wdtpci_get_status(int *status)
0239 {
0240 unsigned char new_status;
0241 unsigned long flags;
0242
0243 spin_lock_irqsave(&wdtpci_lock, flags);
0244 new_status = inb(WDT_SR);
0245 spin_unlock_irqrestore(&wdtpci_lock, flags);
0246
0247 *status = 0;
0248 if (new_status & WDC_SR_ISOI0)
0249 *status |= WDIOF_EXTERN1;
0250 if (new_status & WDC_SR_ISII1)
0251 *status |= WDIOF_EXTERN2;
0252 if (type == 501) {
0253 if (!(new_status & WDC_SR_TGOOD))
0254 *status |= WDIOF_OVERHEAT;
0255 if (!(new_status & WDC_SR_PSUOVER))
0256 *status |= WDIOF_POWEROVER;
0257 if (!(new_status & WDC_SR_PSUUNDR))
0258 *status |= WDIOF_POWERUNDER;
0259 if (tachometer) {
0260 if (!(new_status & WDC_SR_FANGOOD))
0261 *status |= WDIOF_FANFAULT;
0262 }
0263 }
0264 return 0;
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274 static int wdtpci_get_temperature(int *temperature)
0275 {
0276 unsigned short c;
0277 unsigned long flags;
0278 spin_lock_irqsave(&wdtpci_lock, flags);
0279 c = inb(WDT_RT);
0280 udelay(8);
0281 spin_unlock_irqrestore(&wdtpci_lock, flags);
0282 *temperature = (c * 11 / 15) + 7;
0283 return 0;
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
0297 {
0298
0299
0300
0301
0302 unsigned char status;
0303
0304 spin_lock(&wdtpci_lock);
0305
0306 status = inb(WDT_SR);
0307 udelay(8);
0308
0309 pr_crit("status %d\n", status);
0310
0311 if (type == 501) {
0312 if (!(status & WDC_SR_TGOOD)) {
0313 pr_crit("Overheat alarm (%d)\n", inb(WDT_RT));
0314 udelay(8);
0315 }
0316 if (!(status & WDC_SR_PSUOVER))
0317 pr_crit("PSU over voltage\n");
0318 if (!(status & WDC_SR_PSUUNDR))
0319 pr_crit("PSU under voltage\n");
0320 if (tachometer) {
0321 if (!(status & WDC_SR_FANGOOD))
0322 pr_crit("Possible fan fault\n");
0323 }
0324 }
0325 if (!(status & WDC_SR_WCCR)) {
0326 #ifdef SOFTWARE_REBOOT
0327 #ifdef ONLY_TESTING
0328 pr_crit("Would Reboot\n");
0329 #else
0330 pr_crit("Initiating system reboot\n");
0331 emergency_restart();
0332 #endif
0333 #else
0334 pr_crit("Reset in 5ms\n");
0335 #endif
0336 }
0337 spin_unlock(&wdtpci_lock);
0338 return IRQ_HANDLED;
0339 }
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 static ssize_t wdtpci_write(struct file *file, const char __user *buf,
0354 size_t count, loff_t *ppos)
0355 {
0356 if (count) {
0357 if (!nowayout) {
0358 size_t i;
0359
0360
0361 expect_close = 0;
0362
0363 for (i = 0; i != count; i++) {
0364 char c;
0365 if (get_user(c, buf + i))
0366 return -EFAULT;
0367 if (c == 'V')
0368 expect_close = 42;
0369 }
0370 }
0371 wdtpci_ping();
0372 }
0373 return count;
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 static long wdtpci_ioctl(struct file *file, unsigned int cmd,
0388 unsigned long arg)
0389 {
0390 void __user *argp = (void __user *)arg;
0391 int __user *p = argp;
0392 int new_heartbeat;
0393 int status;
0394
0395 struct watchdog_info ident = {
0396 .options = WDIOF_SETTIMEOUT|
0397 WDIOF_MAGICCLOSE|
0398 WDIOF_KEEPALIVEPING,
0399 .firmware_version = 1,
0400 .identity = "PCI-WDT500/501",
0401 };
0402
0403
0404 ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
0405 if (type == 501) {
0406 ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|
0407 WDIOF_POWEROVER);
0408 if (tachometer)
0409 ident.options |= WDIOF_FANFAULT;
0410 }
0411
0412 switch (cmd) {
0413 case WDIOC_GETSUPPORT:
0414 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
0415 case WDIOC_GETSTATUS:
0416 wdtpci_get_status(&status);
0417 return put_user(status, p);
0418 case WDIOC_GETBOOTSTATUS:
0419 return put_user(0, p);
0420 case WDIOC_KEEPALIVE:
0421 wdtpci_ping();
0422 return 0;
0423 case WDIOC_SETTIMEOUT:
0424 if (get_user(new_heartbeat, p))
0425 return -EFAULT;
0426 if (wdtpci_set_heartbeat(new_heartbeat))
0427 return -EINVAL;
0428 wdtpci_ping();
0429 fallthrough;
0430 case WDIOC_GETTIMEOUT:
0431 return put_user(heartbeat, p);
0432 default:
0433 return -ENOTTY;
0434 }
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 static int wdtpci_open(struct inode *inode, struct file *file)
0450 {
0451 if (test_and_set_bit(0, &open_lock))
0452 return -EBUSY;
0453
0454 if (nowayout)
0455 __module_get(THIS_MODULE);
0456
0457
0458
0459 wdtpci_start();
0460 return stream_open(inode, file);
0461 }
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 static int wdtpci_release(struct inode *inode, struct file *file)
0476 {
0477 if (expect_close == 42) {
0478 wdtpci_stop();
0479 } else {
0480 pr_crit("Unexpected close, not stopping timer!\n");
0481 wdtpci_ping();
0482 }
0483 expect_close = 0;
0484 clear_bit(0, &open_lock);
0485 return 0;
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499 static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
0500 size_t count, loff_t *ptr)
0501 {
0502 int temperature;
0503
0504 if (wdtpci_get_temperature(&temperature))
0505 return -EFAULT;
0506
0507 if (copy_to_user(buf, &temperature, 1))
0508 return -EFAULT;
0509
0510 return 1;
0511 }
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521 static int wdtpci_temp_open(struct inode *inode, struct file *file)
0522 {
0523 return stream_open(inode, file);
0524 }
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534 static int wdtpci_temp_release(struct inode *inode, struct file *file)
0535 {
0536 return 0;
0537 }
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
0552 void *unused)
0553 {
0554 if (code == SYS_DOWN || code == SYS_HALT)
0555 wdtpci_stop();
0556 return NOTIFY_DONE;
0557 }
0558
0559
0560
0561
0562
0563
0564 static const struct file_operations wdtpci_fops = {
0565 .owner = THIS_MODULE,
0566 .llseek = no_llseek,
0567 .write = wdtpci_write,
0568 .unlocked_ioctl = wdtpci_ioctl,
0569 .compat_ioctl = compat_ptr_ioctl,
0570 .open = wdtpci_open,
0571 .release = wdtpci_release,
0572 };
0573
0574 static struct miscdevice wdtpci_miscdev = {
0575 .minor = WATCHDOG_MINOR,
0576 .name = "watchdog",
0577 .fops = &wdtpci_fops,
0578 };
0579
0580 static const struct file_operations wdtpci_temp_fops = {
0581 .owner = THIS_MODULE,
0582 .llseek = no_llseek,
0583 .read = wdtpci_temp_read,
0584 .open = wdtpci_temp_open,
0585 .release = wdtpci_temp_release,
0586 };
0587
0588 static struct miscdevice temp_miscdev = {
0589 .minor = TEMP_MINOR,
0590 .name = "temperature",
0591 .fops = &wdtpci_temp_fops,
0592 };
0593
0594
0595
0596
0597
0598
0599 static struct notifier_block wdtpci_notifier = {
0600 .notifier_call = wdtpci_notify_sys,
0601 };
0602
0603
0604 static int wdtpci_init_one(struct pci_dev *dev,
0605 const struct pci_device_id *ent)
0606 {
0607 int ret = -EIO;
0608
0609 dev_count++;
0610 if (dev_count > 1) {
0611 pr_err("This driver only supports one device\n");
0612 return -ENODEV;
0613 }
0614
0615 if (type != 500 && type != 501) {
0616 pr_err("unknown card type '%d'\n", type);
0617 return -ENODEV;
0618 }
0619
0620 if (pci_enable_device(dev)) {
0621 pr_err("Not possible to enable PCI Device\n");
0622 return -ENODEV;
0623 }
0624
0625 if (pci_resource_start(dev, 2) == 0x0000) {
0626 pr_err("No I/O-Address for card detected\n");
0627 ret = -ENODEV;
0628 goto out_pci;
0629 }
0630
0631 if (pci_request_region(dev, 2, "wdt_pci")) {
0632 pr_err("I/O address 0x%llx already in use\n",
0633 (unsigned long long)pci_resource_start(dev, 2));
0634 goto out_pci;
0635 }
0636
0637 irq = dev->irq;
0638 io = pci_resource_start(dev, 2);
0639
0640 if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
0641 "wdt_pci", &wdtpci_miscdev)) {
0642 pr_err("IRQ %d is not free\n", irq);
0643 goto out_reg;
0644 }
0645
0646 pr_info("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
0647 (unsigned long long)io, irq);
0648
0649
0650
0651 if (wdtpci_set_heartbeat(heartbeat)) {
0652 wdtpci_set_heartbeat(WD_TIMO);
0653 pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
0654 WD_TIMO);
0655 }
0656
0657 ret = register_reboot_notifier(&wdtpci_notifier);
0658 if (ret) {
0659 pr_err("cannot register reboot notifier (err=%d)\n", ret);
0660 goto out_irq;
0661 }
0662
0663 if (type == 501) {
0664 ret = misc_register(&temp_miscdev);
0665 if (ret) {
0666 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0667 TEMP_MINOR, ret);
0668 goto out_rbt;
0669 }
0670 }
0671
0672 ret = misc_register(&wdtpci_miscdev);
0673 if (ret) {
0674 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0675 WATCHDOG_MINOR, ret);
0676 goto out_misc;
0677 }
0678
0679 pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
0680 heartbeat, nowayout);
0681 if (type == 501)
0682 pr_info("Fan Tachometer is %s\n",
0683 tachometer ? "Enabled" : "Disabled");
0684
0685 ret = 0;
0686 out:
0687 return ret;
0688
0689 out_misc:
0690 if (type == 501)
0691 misc_deregister(&temp_miscdev);
0692 out_rbt:
0693 unregister_reboot_notifier(&wdtpci_notifier);
0694 out_irq:
0695 free_irq(irq, &wdtpci_miscdev);
0696 out_reg:
0697 pci_release_region(dev, 2);
0698 out_pci:
0699 pci_disable_device(dev);
0700 goto out;
0701 }
0702
0703
0704 static void wdtpci_remove_one(struct pci_dev *pdev)
0705 {
0706
0707
0708 misc_deregister(&wdtpci_miscdev);
0709 if (type == 501)
0710 misc_deregister(&temp_miscdev);
0711 unregister_reboot_notifier(&wdtpci_notifier);
0712 free_irq(irq, &wdtpci_miscdev);
0713 pci_release_region(pdev, 2);
0714 pci_disable_device(pdev);
0715 dev_count--;
0716 }
0717
0718
0719 static const struct pci_device_id wdtpci_pci_tbl[] = {
0720 {
0721 .vendor = PCI_VENDOR_ID_ACCESSIO,
0722 .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
0723 .subvendor = PCI_ANY_ID,
0724 .subdevice = PCI_ANY_ID,
0725 },
0726 { 0, },
0727 };
0728 MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
0729
0730
0731 static struct pci_driver wdtpci_driver = {
0732 .name = "wdt_pci",
0733 .id_table = wdtpci_pci_tbl,
0734 .probe = wdtpci_init_one,
0735 .remove = wdtpci_remove_one,
0736 };
0737
0738 module_pci_driver(wdtpci_driver);
0739
0740 MODULE_AUTHOR("JP Nollmann, Alan Cox");
0741 MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
0742 MODULE_LICENSE("GPL");