/* charqueue.c
 *
 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
 * 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; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */

/*
 *  Simple character queue implementation for Linux kernel mode.
 */

#include "charqueue.h"

#define MYDRVNAME "charqueue"

#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail)



struct CHARQUEUE_Tag {
	int alloc_size;
	int nslots;
	spinlock_t lock;
	int head, tail;
	unsigned char buf[0];
};



CHARQUEUE *visor_charqueue_create(ulong nslots)
{
	int alloc_size = sizeof(CHARQUEUE) + nslots + 1;
	CHARQUEUE *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);

	if (cq == NULL) {
		ERRDRV("visor_charqueue_create allocation failed (alloc_size=%d)",
		       alloc_size);
		return NULL;
	}
	cq->alloc_size = alloc_size;
	cq->nslots = nslots;
	cq->head = cq->tail = 0;
	spin_lock_init(&cq->lock);
	return cq;
}
EXPORT_SYMBOL_GPL(visor_charqueue_create);



void visor_charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c)
{
	int alloc_slots = charqueue->nslots+1;  /* 1 slot is always empty */

	spin_lock(&charqueue->lock);
	charqueue->head = (charqueue->head+1) % alloc_slots;
	if (charqueue->head == charqueue->tail)
		/* overflow; overwrite the oldest entry */
		charqueue->tail = (charqueue->tail+1) % alloc_slots;
	charqueue->buf[charqueue->head] = c;
	spin_unlock(&charqueue->lock);
}
EXPORT_SYMBOL_GPL(visor_charqueue_enqueue);



BOOL visor_charqueue_is_empty(CHARQUEUE *charqueue)
{
	BOOL b;

	spin_lock(&charqueue->lock);
	b = IS_EMPTY(charqueue);
	spin_unlock(&charqueue->lock);
	return b;
}
EXPORT_SYMBOL_GPL(visor_charqueue_is_empty);



static int charqueue_dequeue_1(CHARQUEUE *charqueue)
{
	int alloc_slots = charqueue->nslots + 1;  /* 1 slot is always empty */

	if (IS_EMPTY(charqueue))
		return -1;
	charqueue->tail = (charqueue->tail+1) % alloc_slots;
	return charqueue->buf[charqueue->tail];
}



int charqueue_dequeue(CHARQUEUE *charqueue)
{
	int rc;

	spin_lock(&charqueue->lock);
	rc = charqueue_dequeue_1(charqueue);
	spin_unlock(&charqueue->lock);
	return rc;
}



int visor_charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n)
{
	int rc, counter = 0, c;

	spin_lock(&charqueue->lock);
	for (;;) {
		if (n <= 0)
			break;  /* no more buffer space */
		c = charqueue_dequeue_1(charqueue);
		if (c < 0)
			break;  /* no more input */
		*buf = (unsigned char)(c);
		buf++;
		n--;
		counter++;
	}
	rc = counter;
	spin_unlock(&charqueue->lock);
	return rc;
}
EXPORT_SYMBOL_GPL(visor_charqueue_dequeue_n);



void visor_charqueue_destroy(CHARQUEUE *charqueue)
{
	if (charqueue == NULL)
		return;
	kfree(charqueue);
}
EXPORT_SYMBOL_GPL(visor_charqueue_destroy);
