/** Enable PIO for specified I/O range. * * @param pio_addr I/O start address. * @param size Size of the I/O region. * @param virt Virtual address for application's * PIO operations. Can be NULL for PMIO. * * @return EOK on success. * @return Negative error code on failure. * */ int pio_enable(void *pio_addr, size_t size, void **virt) { #ifdef IO_SPACE_BOUNDARY if (pio_addr < IO_SPACE_BOUNDARY) { if (virt) *virt = pio_addr; return iospace_enable(task_get_id(), pio_addr, size); } #else (void) iospace_enable; #endif if (!virt) return EINVAL; void *phys_frame = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); size_t offset = pio_addr - phys_frame; size_t pages = SIZE2PAGES(offset + size); void *virt_page; int rc = physmem_map(phys_frame, pages, AS_AREA_READ | AS_AREA_WRITE, &virt_page); if (rc != EOK) return rc; *virt = virt_page + offset; return EOK; }
/** Get time of day * * The time variables are memory mapped (read-only) from kernel which * updates them periodically. * * As it is impossible to read 2 values atomically, we use a trick: * First we read the seconds, then we read the microseconds, then we * read the seconds again. If a second elapsed in the meantime, set * the microseconds to zero. * * This assures that the values returned by two subsequent calls * to gettimeofday() are monotonous. * */ int gettimeofday(struct timeval *tv, struct timezone *tz) { if (ktime == NULL) { uintptr_t faddr; int rc = sysinfo_get_value("clock.faddr", &faddr); if (rc != EOK) { errno = rc; return -1; } void *addr; rc = physmem_map((void *) faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE, &addr); if (rc != EOK) { as_area_destroy(addr); errno = rc; return -1; } ktime = addr; } if (tz) { tz->tz_minuteswest = 0; tz->tz_dsttime = DST_NONE; } sysarg_t s2 = ktime->seconds2; read_barrier(); tv->tv_usec = ktime->useconds; read_barrier(); sysarg_t s1 = ktime->seconds1; if (s1 != s2) { tv->tv_sec = max(s1, s2); tv->tv_usec = 0; } else tv->tv_sec = s1; return 0; }