// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (c) 1998-2001 Vojtech Pavlik
 */

/*
 * PDPI Lightning 4 gamecard driver for Linux.
 */

#include <asm/io.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gameport.h>

#define L4_PORT			0x201
#define L4_SELECT_ANALOG	0xa4
#define L4_SELECT_DIGITAL	0xa5
#define L4_SELECT_SECONDARY	0xa6
#define L4_CMD_ID		0x80
#define L4_CMD_GETCAL		0x92
#define L4_CMD_SETCAL		0x93
#define L4_ID			0x04
#define L4_BUSY			0x01
#define L4_TIMEOUT		80	/* 80 us */

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PDPI Lightning 4 gamecard driver");
MODULE_LICENSE("GPL");

struct l4 {
	struct gameport *gameport;
	unsigned char port;
};

static struct l4 l4_ports[8];

/*
 * l4_wait_ready() waits for the L4 to become ready.
 */

static int l4_wait_ready(void)
{
	unsigned int t = L4_TIMEOUT;

	while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
	return -(t <= 0);
}

/*
 * l4_cooked_read() reads data from the Lightning 4.
 */

static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
	struct l4 *l4 = gameport->port_data;
	unsigned char status;
	int i, result = -1;

	outb(L4_SELECT_ANALOG, L4_PORT);
	outb(L4_SELECT_DIGITAL + (l4->port >> 2), L4_PORT);

	if (inb(L4_PORT) & L4_BUSY) goto fail;
	outb(l4->port & 3, L4_PORT);

	if (l4_wait_ready()) goto fail;
	status = inb(L4_PORT);

	for (i = 0; i < 4; i++)
		if (status & (1 << i)) {
			if (l4_wait_ready()) goto fail;
			axes[i] = inb(L4_PORT);
			if (axes[i] > 252) axes[i] = -1;
		}

	if (status & 0x10) {
		if (l4_wait_ready()) goto fail;
		*buttons = inb(L4_PORT) & 0x0f;
	}

	result = 0;

fail:	outb(L4_SELECT_ANALOG, L4_PORT);
	return result;
}

static int l4_open(struct gameport *gameport, int mode)
{
	struct l4 *l4 = gameport->port_data;

        if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
		return -1;
	outb(L4_SELECT_ANALOG, L4_PORT);
	return 0;
}

/*
 * l4_getcal() reads the L4 with calibration values.
 */

static int l4_getcal(int port, int *cal)
{
	int i, result = -1;

	outb(L4_SELECT_ANALOG, L4_PORT);
	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
	if (inb(L4_PORT) & L4_BUSY)
		goto out;

	outb(L4_CMD_GETCAL, L4_PORT);
	if (l4_wait_ready())
		goto out;

	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
		goto out;

	if (l4_wait_ready())
		goto out;
        outb(port & 3, L4_PORT);

	for (i = 0; i < 4; i++) {
		if (l4_wait_ready())
			goto out;
		cal[i] = inb(L4_PORT);
	}

	result = 0;

out:	outb(L4_SELECT_ANALOG, L4_PORT);
	return result;
}

/*
 * l4_setcal() programs the L4 with calibration values.
 */

static int l4_setcal(int port, int *cal)
{
	int i, result = -1;

	outb(L4_SELECT_ANALOG, L4_PORT);
	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
	if (inb(L4_PORT) & L4_BUSY)
		goto out;

	outb(L4_CMD_SETCAL, L4_PORT);
	if (l4_wait_ready())
		goto out;

	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
		goto out;

	if (l4_wait_ready())
		goto out;
        outb(port & 3, L4_PORT);

	for (i = 0; i < 4; i++) {
		if (l4_wait_ready())
			goto out;
		outb(cal[i], L4_PORT);
	}

	result = 0;

out:	outb(L4_SELECT_ANALOG, L4_PORT);
	return result;
}

/*
 * l4_calibrate() calibrates the L4 for the attached device, so
 * that the device's resistance fits into the L4's 8-bit range.
 */

static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
{
	int i, t;
	int cal[4];
	struct l4 *l4 = gameport->port_data;

	if (l4_getcal(l4->port, cal))
		return -1;

	for (i = 0; i < 4; i++) {
		t = (max[i] * cal[i]) / 200;
		t = (t < 1) ? 1 : ((t > 255) ? 255 : t);
		axes[i] = (axes[i] < 0) ? -1 : (axes[i] * cal[i]) / t;
		axes[i] = (axes[i] > 252) ? 252 : axes[i];
		cal[i] = t;
	}

	if (l4_setcal(l4->port, cal))
		return -1;

	return 0;
}

static int __init l4_create_ports(int card_no)
{
	struct l4 *l4;
	struct gameport *port;
	int i, idx;

	for (i = 0; i < 4; i++) {

		idx = card_no * 4 + i;
		l4 = &l4_ports[idx];

		if (!(l4->gameport = port = gameport_allocate_port())) {
			printk(KERN_ERR "lightning: Memory allocation failed\n");
			while (--i >= 0) {
				gameport_free_port(l4->gameport);
				l4->gameport = NULL;
			}
			return -ENOMEM;
		}
		l4->port = idx;

		port->port_data = l4;
		port->open = l4_open;
		port->cooked_read = l4_cooked_read;
		port->calibrate = l4_calibrate;

		gameport_set_name(port, "PDPI Lightning 4");
		gameport_set_phys(port, "isa%04x/gameport%d", L4_PORT, idx);

		if (idx == 0)
			port->io = L4_PORT;
	}

	return 0;
}

static int __init l4_add_card(int card_no)
{
	int cal[4] = { 255, 255, 255, 255 };
	int i, rev, result;
	struct l4 *l4;

	outb(L4_SELECT_ANALOG, L4_PORT);
	outb(L4_SELECT_DIGITAL + card_no, L4_PORT);

	if (inb(L4_PORT) & L4_BUSY)
		return -1;
	outb(L4_CMD_ID, L4_PORT);

	if (l4_wait_ready())
		return -1;

	if (inb(L4_PORT) != L4_SELECT_DIGITAL + card_no)
		return -1;

	if (l4_wait_ready())
		return -1;
	if (inb(L4_PORT) != L4_ID)
		return -1;

	if (l4_wait_ready())
		return -1;
	rev = inb(L4_PORT);

	if (!rev)
		return -1;

	result = l4_create_ports(card_no);
	if (result)
		return result;

	printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
		card_no ? "secondary" : "primary", rev >> 4, rev, L4_PORT);

	for (i = 0; i < 4; i++) {
		l4 = &l4_ports[card_no * 4 + i];

		if (rev > 0x28)		/* on 2.9+ the setcal command works correctly */
			l4_setcal(l4->port, cal);
		gameport_register_port(l4->gameport);
	}

	return 0;
}

static int __init l4_init(void)
{
	int i, cards = 0;

	if (!request_region(L4_PORT, 1, "lightning"))
		return -EBUSY;

	for (i = 0; i < 2; i++)
		if (l4_add_card(i) == 0)
			cards++;

	outb(L4_SELECT_ANALOG, L4_PORT);

	if (!cards) {
		release_region(L4_PORT, 1);
		return -ENODEV;
	}

	return 0;
}

static void __exit l4_exit(void)
{
	int i;
	int cal[4] = { 59, 59, 59, 59 };

	for (i = 0; i < 8; i++)
		if (l4_ports[i].gameport) {
			l4_setcal(l4_ports[i].port, cal);
			gameport_unregister_port(l4_ports[i].gameport);
		}

	outb(L4_SELECT_ANALOG, L4_PORT);
	release_region(L4_PORT, 1);
}

module_init(l4_init);
module_exit(l4_exit);
