Messages in this thread | | | Subject | Re: [PATCH] RTC: Add mmap method to rtc character driver | From | Jim Gettys <> | Date | Tue, 25 Jul 2006 14:00:31 -0400 |
| |
Actually, it was Keith Packard who asked for this (and we've asked for it before in the past).
I will note, that if my memory serves me right, the first X driver we ever did (1984) had this feature.
Regards, - Jim
("X is an exercise in avoiding system calls.")
P.S. my name is spelled "Gettys".
On Tue, 2006-07-25 at 13:41 -0400, Neil Horman wrote: > Hey- > At OLS last week, During Dave Jones Userspace Sucks presentation, Jim > Geddys and some of the Xorg guys noted that they would be able to stop using gettimeofday > so frequently, if they had some other way to get a millisecond resolution timer > in userspace, one that they could perhaps read from a memory mapped page. I was > right behind them and though that seemed like a reasonable request, so I've > taken a stab at it. This patch allows for a page to be mmaped from /dev/rtc > character interface, the first 4 bytes of which provide a regularly increasing > count, once every rtc interrupt. The frequency is of course controlled by the > regular ioctls provided by the rtc driver. I've done some basic testing on it, > and it seems to work well. > > Thanks And Regards > Neil > > Signed-off-by: Neil Horman > > > > rtc.c | 41 ++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 40 insertions(+), 1 deletion(-) > > > diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c > index 6e6a7c7..4ed673e 100644 > --- a/drivers/char/rtc.c > +++ b/drivers/char/rtc.c > @@ -48,9 +48,10 @@ > * CONFIG_HPET_EMULATE_RTC > * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. > * 1.12ac Alan Cox: Allow read access to the day of week register > + * 1.12b Neil Horman: Allow memory mapping of /dev/rtc > */ > > -#define RTC_VERSION "1.12ac" > +#define RTC_VERSION "1.12b" > > /* > * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with > @@ -183,6 +184,8 @@ static int rtc_proc_open(struct inode *i > */ > static unsigned long rtc_status = 0; /* bitmapped status byte. */ > static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */ > +#define BUF_SIZE (PAGE_SIZE/sizeof(unsigned long)) > +static unsigned long rtc_irq_buf[BUF_SIZE] __attribute__ ((aligned (PAGE_SIZE))); > static unsigned long rtc_irq_data = 0; /* our output to the world */ > static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ > > @@ -230,6 +233,7 @@ static inline unsigned char rtc_is_updat > > irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) > { > + unsigned long *count_ptr = (unsigned long *)rtc_irq_buf; > /* > * Can be an alarm interrupt, update complete interrupt, > * or a periodic interrupt. We store the status in the > @@ -265,6 +269,7 @@ irqreturn_t rtc_interrupt(int irq, void > > kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); > > + *count_ptr = (*count_ptr)++; > return IRQ_HANDLED; > } > #endif > @@ -389,6 +394,37 @@ static ssize_t rtc_read(struct file *fil > #endif > } > > +static int rtc_mmap(struct file *file, struct vm_area_struct *vma) > +{ > + unsigned long rtc_addr; > + unsigned long *count_ptr = rtc_irq_buf; > + > + if (vma->vm_end - vma->vm_start != PAGE_SIZE) > + return -EINVAL; > + > + if (vma->vm_flags & VM_WRITE) > + return -EPERM; > + > + if (PAGE_SIZE > (1 << 16)) > + return -ENOSYS; > + > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > + > + rtc_addr = __pa(rtc_irq_buf); > + rtc_addr &= ~(PAGE_SIZE - 1); > + rtc_addr &= -1; > + > + if (remap_pfn_range(vma, vma->vm_start, rtc_addr >> PAGE_SHIFT, > + PAGE_SIZE, vma->vm_page_prot)) { > + printk(KERN_ERR "remap_pfn_range failed in rtc.c\n"); > + return -EAGAIN; > + } > + > + *count_ptr = 0; > + return 0; > + > +} > + > static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) > { > struct rtc_time wtime; > @@ -890,6 +926,7 @@ static const struct file_operations rtc_ > .owner = THIS_MODULE, > .llseek = no_llseek, > .read = rtc_read, > + .mmap = rtc_mmap, > #ifdef RTC_IRQ > .poll = rtc_poll, > #endif > @@ -1082,6 +1119,8 @@ no_irq: > no_irq2: > #endif > > + memset(rtc_irq_buf,0,PAGE_SIZE); > + > (void) init_sysctl(); > > printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n"); -- Jim Gettys One Laptop Per Child
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |