// 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);
