Release 4.15 drivers/isdn/hardware/eicon/s_4bri.c
  
  
  
/*
 *
 Copyright (c) Eicon Networks, 2002.
 *
 This source file is supplied for the use with
 Eicon Networks range of DIVA Server Adapters.
 *
 Eicon File Revision :    2.1
 *
 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; either version 2, or (at your option)
 any later version.
 *
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.
 *
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
#include "platform.h"
#include "di_defs.h"
#include "pc.h"
#include "pr_pc.h"
#include "di.h"
#include "mi_pc.h"
#include "pc_maint.h"
#include "divasync.h"
#include "pc_init.h"
#include "io.h"
#include "helpers.h"
#include "dsrv4bri.h"
#include "dsp_defs.h"
#include "sdp_hdr.h"
/*****************************************************************************/
#define	MAX_XLOG_SIZE	(64 * 1024)
/* --------------------------------------------------------------------------
   Recovery XLOG from QBRI Card
   -------------------------------------------------------------------------- */
static void qBri_cpu_trapped(PISDN_ADAPTER IoAdapter) {
	byte  __iomem *base;
	word *Xlog;
	dword   regs[4], TrapID, offset, size;
	Xdesc   xlogDesc;
	int factor = (IoAdapter->tasks == 1) ? 1 : 2;
/*
 *      check for trapped MIPS 46xx CPU, dump exception frame
 */
	base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
	offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor);
	TrapID = READ_DWORD(&base[0x80]);
	if ((TrapID == 0x99999999) || (TrapID == 0x99999901))
	{
		dump_trap_frame(IoAdapter, &base[0x90]);
		IoAdapter->trapped = 1;
	}
	regs[0] = READ_DWORD((base + offset) + 0x70);
	regs[1] = READ_DWORD((base + offset) + 0x74);
	regs[2] = READ_DWORD((base + offset) + 0x78);
	regs[3] = READ_DWORD((base + offset) + 0x7c);
	regs[0] &= IoAdapter->MemorySize - 1;
	if ((regs[0] >= offset)
	    && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1))
	{
		if (!(Xlog = (word *)diva_os_malloc(0, MAX_XLOG_SIZE))) {
			DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
			return;
		}
		size = offset + (IoAdapter->MemorySize >> factor) - regs[0];
		if (size > MAX_XLOG_SIZE)
			size = MAX_XLOG_SIZE;
		memcpy_fromio(Xlog, &base[regs[0]], size);
		xlogDesc.buf = Xlog;
		xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]);
		xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]);
		dump_xlog_buffer(IoAdapter, &xlogDesc);
		diva_os_free(0, Xlog);
		IoAdapter->trapped = 2;
	}
	DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 371 | 99.20% | 2 | 40.00% | 
| Al Viro | 2 | 0.53% | 2 | 40.00% | 
| Joe Perches | 1 | 0.27% | 1 | 20.00% | 
| Total | 374 | 100.00% | 5 | 100.00% | 
/* --------------------------------------------------------------------------
   Reset QBRI Hardware
   -------------------------------------------------------------------------- */
static void reset_qBri_hardware(PISDN_ADAPTER IoAdapter) {
	word volatile __iomem *qBriReset;
	byte  volatile __iomem *qBriCntrl;
	byte  volatile __iomem *p;
	qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
	WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET);
	diva_os_wait(1);
	WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET);
	diva_os_wait(1);
	WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM);
	diva_os_wait(1);
	WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM);
	diva_os_wait(1);
	DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
	qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
	WRITE_DWORD(p, 0);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
	DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
		DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
		}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 165 | 97.63% | 2 | 66.67% | 
| Al Viro | 4 | 2.37% | 1 | 33.33% | 
| Total | 169 | 100.00% | 3 | 100.00% | 
/* --------------------------------------------------------------------------
   Start Card CPU
   -------------------------------------------------------------------------- */
void start_qBri_hardware(PISDN_ADAPTER IoAdapter) {
	byte volatile __iomem *qBriReset;
	byte volatile __iomem *p;
	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
	WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK);
	diva_os_wait(2);
	WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
	diva_os_wait(10);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
	DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
		}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 85 | 97.70% | 2 | 66.67% | 
| Al Viro | 2 | 2.30% | 1 | 33.33% | 
| Total | 87 | 100.00% | 3 | 100.00% | 
/* --------------------------------------------------------------------------
   Stop Card CPU
   -------------------------------------------------------------------------- */
static void stop_qBri_hardware(PISDN_ADAPTER IoAdapter) {
	byte volatile __iomem *p;
	dword volatile __iomem *qBriReset;
	dword volatile __iomem *qBriIrq;
	dword volatile __iomem *qBriIsacDspReset;
	int rev2 = DIVA_4BRI_REVISION(IoAdapter);
	int reset_offset = rev2 ? (MQ2_BREG_RISC)      : (MQ_BREG_RISC);
	int irq_offset   = rev2 ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST);
	int hw_offset    = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
	if (IoAdapter->ControllerNumber > 0)
		return;
	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	qBriReset = (dword volatile __iomem *)&p[reset_offset];
	qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
/*
 *      clear interrupt line (reset Local Interrupt Test Register)
 */
	WRITE_DWORD(qBriReset, 0);
	WRITE_DWORD(qBriIsacDspReset, 0);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
	WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);	/* disable PCI interrupts */
	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	qBriIrq   = (dword volatile __iomem *)&p[irq_offset];
	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
	DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
		}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 200 | 93.90% | 2 | 40.00% | 
| Al Viro | 12 | 5.63% | 2 | 40.00% | 
| Joe Perches | 1 | 0.47% | 1 | 20.00% | 
| Total | 213 | 100.00% | 5 | 100.00% | 
/* --------------------------------------------------------------------------
   FPGA download
   -------------------------------------------------------------------------- */
#define FPGA_NAME_OFFSET         0x10
static byte *qBri_check_FPGAsrc(PISDN_ADAPTER IoAdapter, char *FileName,
				dword *Length, dword *code) {
	byte *File;
	char *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime;
	dword fpgaFlen, fpgaTlen, fpgaDlen, cnt, year, i;
	if (!(File = (byte *)xdiLoadFile(FileName, Length, 0))) {
		return (NULL);
	}
/*
 *       scan file until FF and put id string into buffer
 */
	for (i = 0; File[i] != 0xff;)
	{
		if (++i >= *Length)
		{
			DBG_FTL(("FPGA download: start of data header not found"))
				xdiFreeFile(File);
			return (NULL);
		}
	}
	*code = i++;
	if ((File[i] & 0xF0) != 0x20)
	{
		DBG_FTL(("FPGA download: data header corrupted"))
			xdiFreeFile(File);
		return (NULL);
	}
	fpgaFlen = (dword)File[FPGA_NAME_OFFSET - 1];
	if (fpgaFlen == 0)
		fpgaFlen = 12;
	fpgaFile = (char *)&File[FPGA_NAME_OFFSET];
	fpgaTlen = (dword)fpgaFile[fpgaFlen + 2];
	if (fpgaTlen == 0)
		fpgaTlen = 10;
	fpgaType = (char *)&fpgaFile[fpgaFlen + 3];
	fpgaDlen = (dword)  fpgaType[fpgaTlen + 2];
	if (fpgaDlen == 0)
		fpgaDlen = 11;
	fpgaDate = (char *)&fpgaType[fpgaTlen + 3];
	fpgaTime = (char *)&fpgaDate[fpgaDlen + 3];
	cnt = (dword)(((File[i] & 0x0F) << 20) + (File[i + 1] << 12)
		      + (File[i + 2] << 4) + (File[i + 3] >> 4));
	if ((dword)(i + (cnt / 8)) > *Length)
	{
		DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
                         FileName, *Length, code + ((cnt + 7) / 8)))
			xdiFreeFile(File);
		return (NULL);
	}
	i = 0;
	do
	{
		while ((fpgaDate[i] != '\0')
		       && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')))
		{
			i++;
		}
		year = 0;
		while ((fpgaDate[i] >= '0') && (fpgaDate[i] <= '9'))
			year = year * 10 + (fpgaDate[i++] - '0');
	} while ((year < 2000) && (fpgaDate[i] != '\0'));
	switch (IoAdapter->cardType) {
	case CARDTYPE_DIVASRV_B_2F_PCI:
		break;
	default:
		if (year >= 2001) {
			IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED;
		}
	}
	DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
                 fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
		return (File);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 508 | 99.41% | 1 | 50.00% | 
| Joe Perches | 3 | 0.59% | 1 | 50.00% | 
| Total | 511 | 100.00% | 2 | 100.00% | 
/******************************************************************************/
#define FPGA_PROG   0x0001		
/* PROG enable low */
#define FPGA_BUSY   0x0002		
/* BUSY high, DONE low */
#define	FPGA_CS     0x000C		
/* Enable I/O pins */
#define FPGA_CCLK   0x0100
#define FPGA_DOUT   0x0400
#define FPGA_DIN    FPGA_DOUT   
/* bidirectional I/O */
int qBri_FPGA_download(PISDN_ADAPTER IoAdapter) {
	int            bit;
	byte           *File;
	dword          code, FileLength;
	word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
	word           val, baseval = FPGA_CS | FPGA_PROG;
	if (DIVA_4BRI_REVISION(IoAdapter))
	{
		char *name;
		switch (IoAdapter->cardType) {
		case CARDTYPE_DIVASRV_B_2F_PCI:
			name = "dsbri2f.bit";
			break;
		case CARDTYPE_DIVASRV_B_2M_V2_PCI:
		case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
			name = "dsbri2m.bit";
			break;
		default:
			name = "ds4bri2.bit";
		}
		File = qBri_check_FPGAsrc(IoAdapter, name,
					  &FileLength, &code);
	}
	else
	{
		File = qBri_check_FPGAsrc(IoAdapter, "ds4bri.bit",
					  &FileLength, &code);
	}
	if (!File) {
		DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
		return (0);
	}
/*
 *      prepare download, pulse PROGRAM pin down.
 */
	WRITE_WORD(addr, baseval & ~FPGA_PROG); /* PROGRAM low pulse */
	WRITE_WORD(addr, baseval);              /* release */
	diva_os_wait(50);  /* wait until FPGA finished internal memory clear */
/*
 *      check done pin, must be low
 */
	if (READ_WORD(addr) & FPGA_BUSY)
	{
		DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
			xdiFreeFile(File);
		DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
		return (0);
	}
/*
 *      put data onto the FPGA
 */
	while (code < FileLength)
	{
		val = ((word)File[code++]) << 3;
		for (bit = 8; bit-- > 0; val <<= 1) /* put byte onto FPGA */
		{
			baseval &= ~FPGA_DOUT;             /* clr  data bit */
			baseval |= (val & FPGA_DOUT);      /* copy data bit */
			WRITE_WORD(addr, baseval);
			WRITE_WORD(addr, baseval | FPGA_CCLK);     /* set CCLK hi */
			WRITE_WORD(addr, baseval | FPGA_CCLK);     /* set CCLK hi */
			WRITE_WORD(addr, baseval);                 /* set CCLK lo */
		}
	}
	xdiFreeFile(File);
	diva_os_wait(100);
	val = READ_WORD(addr);
	DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
	if (!(val & FPGA_BUSY))
	{
		DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
			return (0);
	}
	return (1);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 336 | 96.83% | 2 | 50.00% | 
| Kai Germaschewski | 9 | 2.59% | 1 | 25.00% | 
| Al Viro | 2 | 0.58% | 1 | 25.00% | 
| Total | 347 | 100.00% | 4 | 100.00% | 
static int load_qBri_hardware(PISDN_ADAPTER IoAdapter) {
	return (0);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 14 | 100.00% | 1 | 100.00% | 
| Total | 14 | 100.00% | 1 | 100.00% | 
/* --------------------------------------------------------------------------
   Card ISR
   -------------------------------------------------------------------------- */
static int qBri_ISR(struct _ISDN_ADAPTER *IoAdapter) {
	dword volatile     __iomem *qBriIrq;
	PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList;
	word			i;
	int			serviced = 0;
	byte __iomem *p;
	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
	if (!(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80)) {
		DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
		return (0);
	}
	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
/*
 *      clear interrupt line (reset Local Interrupt Test Register)
 */
	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
	for (i = 0; i < IoAdapter->tasks; ++i)
	{
		IoAdapter = QuadroList->QuadroAdapter[i];
		if (IoAdapter && IoAdapter->Initialized
		    && IoAdapter->tst_irq(&IoAdapter->a))
		{
			IoAdapter->IrqCount++;
			serviced = 1;
			diva_os_schedule_soft_isr(&IoAdapter->isr_soft_isr);
		}
	}
	return (serviced);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 191 | 96.46% | 2 | 50.00% | 
| Al Viro | 7 | 3.54% | 2 | 50.00% | 
| Total | 198 | 100.00% | 4 | 100.00% | 
/* --------------------------------------------------------------------------
   Does disable the interrupt on the card
   -------------------------------------------------------------------------- */
static void disable_qBri_interrupt(PISDN_ADAPTER IoAdapter) {
	dword volatile __iomem *qBriIrq;
	byte __iomem *p;
	if (IoAdapter->ControllerNumber > 0)
		return;
/*
 *      clear interrupt line (reset Local Interrupt Test Register)
 */
	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
	WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);	/* disable PCI interrupts */
	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
	qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 95 | 91.35% | 2 | 40.00% | 
| Al Viro | 8 | 7.69% | 2 | 40.00% | 
| Joe Perches | 1 | 0.96% | 1 | 20.00% | 
| Total | 104 | 100.00% | 5 | 100.00% | 
/* --------------------------------------------------------------------------
   Install Adapter Entry Points
   -------------------------------------------------------------------------- */
static void set_common_qBri_functions(PISDN_ADAPTER IoAdapter) {
	ADAPTER *a;
	a = &IoAdapter->a;
	a->ram_in           = mem_in;
	a->ram_inw          = mem_inw;
	a->ram_in_buffer    = mem_in_buffer;
	a->ram_look_ahead   = mem_look_ahead;
	a->ram_out          = mem_out;
	a->ram_outw         = mem_outw;
	a->ram_out_buffer   = mem_out_buffer;
	a->ram_inc          = mem_inc;
	IoAdapter->out = pr_out;
	IoAdapter->dpc = pr_dpc;
	IoAdapter->tst_irq = scom_test_int;
	IoAdapter->clr_irq  = scom_clear_int;
	IoAdapter->pcm  = (struct pc_maint *)MIPS_MAINT_OFFS;
	IoAdapter->load = load_qBri_hardware;
	IoAdapter->disIrq = disable_qBri_interrupt;
	IoAdapter->rstFnc = reset_qBri_hardware;
	IoAdapter->stop = stop_qBri_hardware;
	IoAdapter->trapFnc = qBri_cpu_trapped;
	IoAdapter->diva_isr_handler = qBri_ISR;
	IoAdapter->a.io = (void *)IoAdapter;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 151 | 100.00% | 1 | 100.00% | 
| Total | 151 | 100.00% | 1 | 100.00% | 
static void set_qBri_functions(PISDN_ADAPTER IoAdapter) {
	if (!IoAdapter->tasks) {
		IoAdapter->tasks = MQ_INSTANCE_COUNT;
	}
	IoAdapter->MemorySize = MQ_MEMORY_SIZE;
	set_common_qBri_functions(IoAdapter);
	diva_os_set_qBri_functions(IoAdapter);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 40 | 100.00% | 1 | 100.00% | 
| Total | 40 | 100.00% | 1 | 100.00% | 
static void set_qBri2_functions(PISDN_ADAPTER IoAdapter) {
	if (!IoAdapter->tasks) {
		IoAdapter->tasks = MQ_INSTANCE_COUNT;
	}
	IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
	set_common_qBri_functions(IoAdapter);
	diva_os_set_qBri2_functions(IoAdapter);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 50 | 100.00% | 1 | 100.00% | 
| Total | 50 | 100.00% | 1 | 100.00% | 
/******************************************************************************/
void prepare_qBri_functions(PISDN_ADAPTER IoAdapter) {
	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 56 | 100.00% | 1 | 100.00% | 
| Total | 56 | 100.00% | 1 | 100.00% | 
void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter) {
	if (!IoAdapter->tasks) {
		IoAdapter->tasks = MQ_INSTANCE_COUNT;
	}
	set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
	if (IoAdapter->tasks > 1) {
		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
	}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 81 | 100.00% | 1 | 100.00% | 
| Total | 81 | 100.00% | 1 | 100.00% | 
/* -------------------------------------------------------------------------- */
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Armin Schindler | 2421 | 97.39% | 2 | 33.33% | 
| Al Viro | 37 | 1.49% | 2 | 33.33% | 
| Joe Perches | 15 | 0.60% | 1 | 16.67% | 
| Kai Germaschewski | 13 | 0.52% | 1 | 16.67% | 
| Total | 2486 | 100.00% | 6 | 100.00% | 
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.