예제 #1
0
static void reset_port(void *arg, long period) {
    parport_t *port = arg;
    long long deadline, reset_time_tsc;
    unsigned char outdata = (port->outdata&~port->reset_mask) ^ port->reset_val;
   
    if(port->reset_time > period/4) port->reset_time = period/4;
    reset_time_tsc = ns2tsc(port->reset_time);

    if(outdata != port->outdata) {
        deadline = port->write_time + reset_time_tsc;
        while(rtapi_get_clocks() < deadline) {}
        rtapi_outb(outdata, port->base_addr);
    }

    outdata = (port->outdata_ctrl&~port->reset_mask_ctrl)^port->reset_val_ctrl;

    if(outdata != port->outdata_ctrl) {
	/* correct for hardware inverters on pins 1, 14, & 17 */
	outdata ^= 0x0B;
        deadline = port->write_time_ctrl + reset_time_tsc;
        while(rtapi_get_clocks() < deadline) {}
        rtapi_outb(outdata, port->base_addr + 2);
    }
}
예제 #2
0
int
tb_ioctl (struct inode *inode, struct file *filp, uint cmd, unsigned long arg)
{
    struct rt_tmbench_context *ctx;
    int ret = 0;
    volatile unsigned long long tsc = 0;

    ctx = (struct rt_tmbench_context *) filp->private_data;

    switch (cmd)
    {
    case RTTST_RTIOC_TMBENCH_START:
    {
        struct rttst_tmbench_config config_buf;
        struct rttst_tmbench_config *config;

        copy_from_user (&config_buf, (void *) arg,
                        sizeof (struct rttst_tmbench_config));
        config = &config_buf;

        down (&ctx->nrt_mutex);

        ctx->period = ns2tsc (config->period);
        ctx->warmup_loops = config->warmup_loops;
        ctx->samples_per_sec = 1000000000 / (long) config->period;
        ctx->histogram_size = config->histogram_size;
        ctx->freeze_max = config->freeze_max;

        if (ctx->histogram_size > 0)
        {
            ctx->histogram_min =
                kmalloc (3 * ctx->histogram_size * sizeof (long), GFP_KERNEL);
            ctx->histogram_max = ctx->histogram_min + config->histogram_size;
            ctx->histogram_avg = ctx->histogram_max + config->histogram_size;

            if (!ctx->histogram_min)
            {
                up (&ctx->nrt_mutex);
                return -ENOMEM;
            }

            memset (ctx->histogram_min, 0,
                    3 * ctx->histogram_size * sizeof (long));
            ctx->bucketsize = config->histogram_bucketsize;
        }

        ctx->result.overall.min = 10000000;
        ctx->result.overall.max = -10000000;
        ctx->result.overall.avg = 0;
        ctx->result.overall.test_loops = 1;
        ctx->result.overall.overruns = 0;

        ctx->warmup = 1;

        ctx->curr.min = 10000000;
        ctx->curr.max = -10000000;
        ctx->curr.avg = 0;
        ctx->curr.overruns = 0;

        //ctx->result_event = &tb_wq;

        ctx->curr.test_loops = 0;

        ctx->mode = RTTST_TMBENCH_HANDLER;
        read_tsc (tsc);
        ctx->start_time = tsc + 1000000;
        ctx->date = ctx->start_time + ctx->period;

        tb_timer_init (timer_proc, &tb_ctx);

        read_tsc (tsc);
        tb_timer_start ((long) (ctx->date - tsc));

        up (&ctx->nrt_mutex);

        break;
    }

    case RTTST_RTIOC_TMBENCH_STOP:
    {
        struct rttst_overall_bench_res *usr_res;

        usr_res = (struct rttst_overall_bench_res *) arg;

        down (&ctx->nrt_mutex);

        if (ctx->mode < 0)
        {
            up (&ctx->nrt_mutex);
            return -EINVAL;
        }

        tb_timer_stop ();

        ctx->mode = -1;

        ctx->result.overall.avg =
            slldiv (ctx->result.overall.avg,
                    (((ctx->result.overall.test_loops) > 1 ?
                      ctx->result.overall.test_loops : 2) - 1));

        copy_to_user (&usr_res->result,
                      &ctx->result.overall, sizeof (struct rttst_bench_res));

        if (ctx->histogram_size)
        {
            int size = ctx->histogram_size * sizeof (long);

            copy_to_user (usr_res->histogram_min, ctx->histogram_min, size);
            copy_to_user (usr_res->histogram_max, ctx->histogram_max, size);
            copy_to_user (usr_res->histogram_avg, ctx->histogram_avg, size);
            kfree (ctx->histogram_min);
        }

        up (&ctx->nrt_mutex);

        free_irq (IRQ_WATCH, &tb_ctx);

        break;
    }

    case RTTST_RTIOC_INTERM_BENCH_RES:
    {
        struct rttst_interm_bench_res *usr_res;

        usr_res = (struct rttst_interm_bench_res *) arg;

        ret = wait_event_interruptible (*(ctx->result_event), ctx->done != 0);
        if (ret < 0)
            return ret;

        ctx->done = 0;

        copy_to_user (usr_res, &ctx->result,
                      sizeof (struct rttst_interm_bench_res));

        break;
    }

    case RTTST_GETCCLK:
    {
        copy_to_user ((void *) arg, &tb_cclk, sizeof (tb_cclk));
        break;
    }

    case RTTST_TMR_START:
    {
        struct timer_info t_info;

        copy_from_user (&t_info, (void *) arg, sizeof (t_info));
        ctx->period = t_info.period_tsc;
        ctx->start_time = t_info.start_tsc;
        ctx->date = ctx->start_time + ctx->period;

        tb_timer_init (user_timer_proc, &tb_ctx);

        read_tsc (tsc);
        tb_timer_start ((long) (ctx->date - tsc));
        break;
    }

    case RTTST_TMR_WAIT:
    {
        ctx->curr.overruns = 0;

        ret = wait_event_interruptible (*(ctx->result_event), ctx->done != 0);
        if (ret < 0)
            return ret;

        ctx->date += ctx->period;
        read_tsc (ctx->start_time);

        //printk("KERNEL: wake up - tsc: %lld, overrun: %ld\n",
        //ctx->start_time, ctx->curr.overruns);

        if (ctx->date <= ctx->start_time)
        {
            while (ctx->date <= ctx->start_time)
            {
                /* set next release point */
                ctx->curr.overruns++;
                ctx->date += ctx->period;
            }
            ret = -ETIMEDOUT;
        }
        ctx->done = 0;
        tb_timer_start ((long) (ctx->date - ctx->start_time));
        copy_to_user ((void *) arg, &(ctx->curr.overruns),
                      sizeof (ctx->curr.overruns));
        break;
    }

    case RTTST_TMR_STOP:
    {
        tb_timer_stop ();
        free_irq (IRQ_WATCH, &tb_ctx);
        break;
    }

    default:
        printk ("%s: bad ioctl code (0x%x)\n", __FUNCTION__, cmd);
        ret = -ENOTTY;
    }

    return ret;
}