vserver 1.9.5.x5
[linux-2.6.git] / drivers / sbus / char / cpwatchdog.c
index e383894..c82abeb 100644 (file)
  * UNKNOWN, MAGICAL MYSTERY REGISTER
  *
  */
-struct wd_timer_regblk {
-       volatile __u16  dcntr;          /* down counter         - hw    */
-       volatile __u16  dcntr_pad;
-       volatile __u16  limit;          /* limit register       - hw    */
-       volatile __u16  limit_pad;
-       volatile __u8   status;         /* status register      - b             */
-       volatile __u8   status_pad;
-       volatile __u16  status_pad2;
-       volatile __u32  pad32;          /* yet more padding                     */
-};
+#define WD_TIMER_REGSZ 16
+#define WD0_OFF                0
+#define WD1_OFF                (WD_TIMER_REGSZ * 1)
+#define WD2_OFF                (WD_TIMER_REGSZ * 2)
+#define PLD_OFF                (WD_TIMER_REGSZ * 3)
 
-struct wd_pld_regblk {
-       volatile __u8   intr_mask;      /* interrupt mask       - b             */
-       volatile __u8   intr_mask_pad;
-       volatile __u16  intr_mask_pad2;
-       volatile __u8   status;         /* device status        - b             */
-       volatile __u8   status_pad;
-       volatile __u16  status_pad2;
-};
+#define WD_DCNTR       0x00
+#define WD_LIMIT       0x04
+#define WD_STATUS      0x08
 
-struct wd_regblk {
-       volatile struct wd_timer_regblk         wd0_regs;
-       volatile struct wd_timer_regblk         wd1_regs;
-       volatile struct wd_timer_regblk         wd2_regs;
-       volatile struct wd_pld_regblk           pld_regs;
-};
+#define PLD_IMASK      (PLD_OFF + 0x00)
+#define PLD_STATUS     (PLD_OFF + 0x04)
 
 /* Individual timer structure 
  */
 struct wd_timer {
        __u16                   timeout;
        __u8                    intr_mask;
-       unsigned char   runstatus;
-       volatile struct wd_timer_regblk* regs;
+       unsigned char           runstatus;
+       void __iomem            *regs;
 };
 
 /* Device structure
@@ -165,7 +151,7 @@ struct wd_device {
        unsigned short  opt_timeout;
        unsigned char   initialized;
        struct wd_timer watchdog[WD_NUMDEVS];
-       volatile struct wd_regblk* regs;
+       void __iomem    *regs;
 };
 
 static struct wd_device wd_dev = { 
@@ -179,11 +165,11 @@ static int wd1_timeout = 0;
 static int wd2_timeout = 0;
 
 #ifdef MODULE
-MODULE_PARM            (wd0_timeout, "i");
+module_param   (wd0_timeout, int, 0);
 MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
-MODULE_PARM    (wd1_timeout, "i");
+module_param   (wd1_timeout, int, 0);
 MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
-MODULE_PARM    (wd2_timeout, "i");
+module_param   (wd2_timeout, int, 0);
 MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
 
 MODULE_AUTHOR
@@ -324,7 +310,7 @@ static int wd_open(struct inode *inode, struct file *f)
                wd_dev.initialized = 1;
        }
 
-       return(0);
+       return(nonseekable_open(inode, f));
 }
 
 static int wd_release(struct inode *inode, struct file *file)
@@ -337,6 +323,7 @@ static int wd_ioctl(struct inode *inode, struct file *file,
 {
        int     setopt                          = 0;
        struct  wd_timer* pTimer        = (struct wd_timer*)file->private_data;
+       void __user *argp = (void __user *)arg;
        struct  watchdog_info info      = {
                0,
                0,
@@ -351,22 +338,20 @@ static int wd_ioctl(struct inode *inode, struct file *file,
        {
                /* Generic Linux IOCTLs */
                case WDIOC_GETSUPPORT:
-                       if(copy_to_user((struct watchdog_info *)arg, 
-                                                       (struct watchdog_info *)&info, 
-                                                       sizeof(struct watchdog_info))) {
+                       if(copy_to_user(argp, &info, sizeof(struct watchdog_info))) {
                                return(-EFAULT);
                        }
                        break;
                case WDIOC_GETSTATUS:
                case WDIOC_GETBOOTSTATUS:
-                       if (put_user(0, (int *) arg))
+                       if (put_user(0, (int __user *)argp))
                                return -EFAULT;
                        break;
                case WDIOC_KEEPALIVE:
                        wd_pingtimer(pTimer);
                        break;
                case WDIOC_SETOPTIONS:
-                       if(copy_from_user(&setopt, (void*) arg, sizeof(unsigned int))) {
+                       if(copy_from_user(&setopt, argp, sizeof(unsigned int))) {
                                return -EFAULT;
                        }
                        if(setopt & WDIOS_DISABLECARD) {
@@ -388,7 +373,7 @@ static int wd_ioctl(struct inode *inode, struct file *file,
                /* Solaris-compatible IOCTLs */
                case WIOCGSTAT:
                        setopt = wd_getstatus(pTimer);
-                       if(copy_to_user((void*)arg, &setopt, sizeof(unsigned int))) {
+                       if(copy_to_user(argp, &setopt, sizeof(unsigned int))) {
                                return(-EFAULT);
                        }
                        break;
@@ -409,10 +394,10 @@ static int wd_ioctl(struct inode *inode, struct file *file,
        return(0);
 }
 
-static ssize_t wd_write(       struct file     *file, 
-                                                       const char              *buf, 
-                                                       size_t                  count, 
-                                                       loff_t                  *ppos)
+static ssize_t wd_write(struct file    *file, 
+                       const char      __user *buf, 
+                       size_t          count, 
+                       loff_t          *ppos)
 {
        struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
 
@@ -420,9 +405,6 @@ static ssize_t wd_write(    struct file     *file,
                return(-EINVAL);
        }
 
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
        if (count) {
                wd_pingtimer(pTimer);
                return 1;
@@ -430,7 +412,7 @@ static ssize_t wd_write(    struct file     *file,
        return 0;
 }
 
-static ssize_t wd_read(struct file * file, char buffer,
+static ssize_t wd_read(struct file * file, char __user *buffer,
                        size_t count, loff_t *ppos)
 {
 #ifdef WD_DEBUG
@@ -499,12 +481,12 @@ static void wd_dumpregs(void)
                                i,
                                wd_getstatus(&wd_dev.watchdog[i]));
        }
-       printk("\tintr_mask  at 0x%lx: 0x%x\n", 
-               (unsigned long)(&wd_dev.regs->pld_regs.intr_mask), 
-               readb(&wd_dev.regs->pld_regs.intr_mask));
-       printk("\tpld_status at 0x%lx: 0x%x\n", 
-               (unsigned long)(&wd_dev.regs->pld_regs.status)
-               readb(&wd_dev.regs->pld_regs.status));
+       printk("\tintr_mask  at %p: 0x%x\n", 
+               wd_dev.regs + PLD_IMASK,
+               readb(wd_dev.regs + PLD_IMASK));
+       printk("\tpld_status at %p: 0x%x\n", 
+               wd_dev.regs + PLD_STATUS
+               readb(wd_dev.regs + PLD_STATUS));
 }
 #endif
 
@@ -517,7 +499,7 @@ static void wd_dumpregs(void)
  */
 static void wd_toggleintr(struct wd_timer* pTimer, int enable)
 {
-       unsigned char curregs = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+       unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK);
        unsigned char setregs = 
                (NULL == pTimer) ? 
                        (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : 
@@ -527,7 +509,7 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable)
                (curregs &= ~setregs):
                (curregs |=  setregs);
 
-       wd_writeb(curregs, &wd_dev.regs->pld_regs.intr_mask);
+       wd_writeb(curregs, wd_dev.regs + PLD_IMASK);
        return;
 }
 
@@ -538,8 +520,8 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable)
  */
 static void wd_pingtimer(struct wd_timer* pTimer)
 {
-       if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
-               wd_readw(&pTimer->regs->dcntr);
+       if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
+               wd_readw(pTimer->regs + WD_DCNTR);
        }
 }
 
@@ -551,7 +533,7 @@ static void wd_pingtimer(struct wd_timer* pTimer)
  */
 static void wd_stoptimer(struct wd_timer* pTimer)
 {
-       if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+       if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
                wd_toggleintr(pTimer, WD_INTR_OFF);
 
                if(wd_dev.isbaddoggie) {
@@ -578,7 +560,7 @@ static void wd_starttimer(struct wd_timer* pTimer)
        }
        pTimer->runstatus &= ~WD_STAT_SVCD;
 
-       wd_writew(pTimer->timeout, &pTimer->regs->limit);
+       wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT);
        wd_toggleintr(pTimer, WD_INTR_ON);
 }
 
@@ -588,7 +570,7 @@ static void wd_starttimer(struct wd_timer* pTimer)
 static void wd_resetbrokentimer(struct wd_timer* pTimer)
 {
        wd_toggleintr(pTimer, WD_INTR_ON);
-       wd_writew(WD_BLIMIT, &pTimer->regs->limit);
+       wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT);
 }
 
 /* Timer device initialization helper.
@@ -597,7 +579,7 @@ static void wd_resetbrokentimer(struct wd_timer* pTimer)
 static int wd_inittimer(int whichdog)
 {
        struct miscdevice                               *whichmisc;
-       volatile struct wd_timer_regblk *whichregs;
+       void __iomem *whichregs;
        char                                                    whichident[8];
        int                                                             whichmask;
        __u16                                                   whichlimit;
@@ -607,7 +589,7 @@ static int wd_inittimer(int whichdog)
                case WD0_ID:
                        whichmisc = &wd0_miscdev;
                        strcpy(whichident, "RIC");
-                       whichregs = &wd_dev.regs->wd0_regs;
+                       whichregs = wd_dev.regs + WD0_OFF;
                        whichmask = WD0_INTR_MASK;
                        whichlimit= (0 == wd0_timeout)  ? 
                                                (wd_dev.opt_timeout): 
@@ -616,7 +598,7 @@ static int wd_inittimer(int whichdog)
                case WD1_ID:
                        whichmisc = &wd1_miscdev;
                        strcpy(whichident, "XIR");
-                       whichregs = &wd_dev.regs->wd1_regs;
+                       whichregs = wd_dev.regs + WD1_OFF;
                        whichmask = WD1_INTR_MASK;
                        whichlimit= (0 == wd1_timeout)  ? 
                                                (wd_dev.opt_timeout): 
@@ -625,7 +607,7 @@ static int wd_inittimer(int whichdog)
                case WD2_ID:
                        whichmisc = &wd2_miscdev;
                        strcpy(whichident, "POR");
-                       whichregs = &wd_dev.regs->wd2_regs;
+                       whichregs = wd_dev.regs + WD2_OFF;
                        whichmask = WD2_INTR_MASK;
                        whichlimit= (0 == wd2_timeout)  ? 
                                                (wd_dev.opt_timeout): 
@@ -690,8 +672,8 @@ static void wd_brokentimer(unsigned long data)
 
 static int wd_getstatus(struct wd_timer* pTimer)
 {
-       unsigned char stat = wd_readb(&pTimer->regs->status);
-       unsigned char intr = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+       unsigned char stat = wd_readb(pTimer->regs + WD_STATUS);
+       unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK);
        unsigned char ret  = WD_STOPPED;
 
        /* determine STOPPED */
@@ -761,7 +743,7 @@ ebus_done:
        }
 
        wd_dev.regs = 
-               ioremap(edev->resource[0].start, sizeof(struct wd_regblk));
+               ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */
 
        if(NULL == wd_dev.regs) {
                printk("%s: unable to map registers\n", WD_OBPNAME);
@@ -809,7 +791,7 @@ static void __exit wd_cleanup(void)
         * also now eventually trip. 
         */
        for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
-               if(WD_S_RUNNING == wd_readb(&wd_dev.watchdog[id].regs->status)) {
+               if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) {
                        if(wd_dev.opt_enable) {
                                printk(KERN_WARNING "%s%i: timer not stopped at release\n",
                                        WD_OBPNAME, id);
@@ -822,7 +804,7 @@ static void __exit wd_cleanup(void)
                                                        "%s%i: defect workaround disabled at release, "\
                                                        "timer expires in ~%01i sec\n",
                                                        WD_OBPNAME, id, 
-                                                       wd_readw(&wd_dev.watchdog[id].regs->limit) / 10);
+                                                       wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10);
                                }
                        }
                }