/* -*- linux-c -*- ------------------------------------------------------- *
 *   
 *   Copyright 2002 H. Peter Anvin - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Bostom MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

#ifndef LINUX_RAID_RAID6_H
#define LINUX_RAID_RAID6_H

#include "types.h"

#ifdef BIT64
# define NBYTES(x) ((x) * 0x0101010101010101UL)
# define NSIZE  8
# define NSHIFT 3
typedef u64 unative_t;
#else
# define NBYTES(x) ((x) * 0x01010101U)
# define NSIZE  4
# define NSHIFT 2
typedef u32 unative_t;
#endif

/* Routine choices */
struct raid6_calls {
	void (*gen_syndrome)(int, size_t, void **);
	int  (*chk_syndrome)(int, size_t, void **);
	int  (*valid)(void);	/* Returns 1 if this routine set is usable */
	const char *name;	/* Name of this routine set */
	int prefer;		/* Has special performance attribute */
};

/* Selected algorithm */
extern struct raid6_calls raid6_call;

/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
void raid6_select_algo(void);

/* Return values from chk_syndrome */
#define RAID6_OK	0
#define RAID6_P_BAD	1
#define RAID6_Q_BAD	2
#define RAID6_PQ_BAD	3

/* Galois field tables */
extern const u8 raid6_gfmul[256][256];
extern const u8 raid6_gfexp[256];
extern const u8 raid6_gfinv[256];
extern const u8 raid6_gfexi[256];

/* Recovery routine */
void raid6_dual_recov(int disks, size_t bytes, int faila, int failb, void **ptrs);

/* Some definitions to allow code to be compiled for testing in userspace */
#ifdef __KERNEL__

# define raid6_jiffies()	jiffies

#else /* ! __KERNEL__ */

#include <stdio.h>
#include <sys/time.h>

#define printk printf

static inline void cpu_relax(void)
{
	/* Nothing */
}

#undef HZ
#define HZ 1000
static inline uint32_t raid6_jiffies(void)
{
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return tv.tv_sec*1000 + tv.tv_usec/1000;
}

#endif /* ! __KERNEL__ */

#endif /* LINUX_RAID_RAID6_H */
