/*
 *
 * Open Hack'Ware BIOS ADB bus support, ported to OpenBIOS
 *
 *  Copyright (c) 2005 Jocelyn Mayer
 *  Copyright (c) 2005 Stefan Reinauer
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License V2
 *   as published by the Free Software Foundation
 *
 *   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.  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., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
 */

#include "config.h"
#include "drivers/drivers.h"
#include "libopenbios/bindings.h"
#include "libc/vsprintf.h"

#include "adb_bus.h"
#include "adb_kbd.h"
#include "adb_mouse.h"

DECLARE_UNNAMED_NODE( adb, 0, sizeof(int));

static void
adb_open(int *idx)
{
	RET(-1);
}

static void
adb_close(int *idx)
{
}

NODE_METHODS( adb ) = {
	{ "open",		adb_open		},
	{ "close",		adb_close		},
};

adb_bus_t *adb_bus_new (void *host,
                        int (*req)(void *host, const uint8_t *snd_buf,
                                   int len, uint8_t *rcv_buf))
{
    adb_bus_t *new;

    new = malloc(sizeof(adb_bus_t));
    if (new == NULL)
        return NULL;
    new->host = host;
    new->req = req;

    return new;
}

/* Check and relocate all ADB devices as suggested in
 * ADB_manager Apple documentation
 */

int adb_bus_init (char *path, adb_bus_t *bus)
{
    char buf[64];
    uint8_t buffer[ADB_BUF_SIZE];
    uint8_t adb_addresses[16] =
        { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, };
    adb_dev_t tmp_device, **cur;
    int address;
    int reloc = 0, next_free = 7;
    int keep;

    fword("new-device");

    push_str("adb");
    fword("device-name");

    push_str("adb");
    fword("device-type");

    if (has_pmu()) {
        push_str("pmu-99");
        fword("encode-string");
        push_str("compatible");
        fword("property");
    } else {
        push_str("adb");
        fword("encode-string");
        push_str("compatible");
        fword("property");
    }

    PUSH(1);
    fword("encode-int");
    push_str("#address-cells");
    fword("property");

    PUSH(0);
    fword("encode-int");
    push_str("#size-cells");
    fword("property");

    BIND_NODE_METHODS(get_cur_dev(), adb);

    snprintf(buf, sizeof(buf), "%s/adb", path);

    /* Reset the bus */
    // ADB_DPRINTF("\n");
    adb_reset(bus);
    cur = &bus->devices;
    memset(&tmp_device, 0, sizeof(adb_dev_t));
    tmp_device.bus = bus;
    for (address = 1; address < 8 && adb_addresses[reloc] > 0;) {
        if (address == ADB_RES) {
            /* Reserved */
            address++;
            continue;
        }
        //ADB_DPRINTF("Check device on ADB address %d\n", address);
        tmp_device.addr = address;
        switch (adb_reg_get(&tmp_device, 3, buffer)) {
        case 0:
            //ADB_DPRINTF("No device on ADB address %d\n", address);
            /* Register this address as free */
            if (adb_addresses[next_free] != 0)
                adb_addresses[next_free++] = address;
            /* Check next ADB address */
            address++;
            break;
        case 2:
           /* One device answered :
            * make it available and relocate it to a free address
            */
            if (buffer[0] == ADB_CHADDR) {
                /* device self test failed */
                ADB_DPRINTF("device on ADB address %d self-test failed "
                            "%02x %02x %02x\n", address,
                            buffer[0], buffer[1], buffer[2]);
                keep = 0;
            } else {
                //ADB_DPRINTF("device on ADB address %d self-test OK\n",
                //            address);
                keep = 1;
            }
            ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n",
                        address, adb_addresses[reloc], reloc);
            buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc];
            if (keep == 1)
                buffer[0] |= 0x20;
            buffer[1] = ADB_CHADDR_NOCOLL;
            if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) {
                ADB_DPRINTF("ADB device relocation failed\n");
                return -1;
            }
            if (keep == 1) {
                *cur = malloc(sizeof(adb_dev_t));
                if (*cur == NULL) {
                    return -1;
                }
                (*cur)->type = address;
                (*cur)->bus = bus;
                (*cur)->addr = adb_addresses[reloc++];
                /* Flush buffers */
                adb_flush(*cur);
                switch ((*cur)->type) {
                case ADB_PROTECT:
                    ADB_DPRINTF("Found one protected device\n");
                    break;
                case ADB_KEYBD:
                    ADB_DPRINTF("Found one keyboard on address %d\n", address);
                    adb_kbd_new(buf, *cur);
                    break;
                case ADB_MOUSE:
                    ADB_DPRINTF("Found one mouse on address %d\n", address);
                    adb_mouse_new(buf, *cur);
                    break;
                case ADB_ABS:
                    ADB_DPRINTF("Found one absolute positioning device\n");
                    break;
                case ADB_MODEM:
                    ADB_DPRINTF("Found one modem\n");
                    break;
                case ADB_RES:
                    ADB_DPRINTF("Found one ADB res device\n");
                    break;
                case ADB_MISC:
                    ADB_DPRINTF("Found one ADB misc device\n");
                    break;
                }
                cur = &((*cur)->next);
            }
            break;
        case 1:
        case 3 ... 7:
            /* SHOULD NOT HAPPEN : register 3 is always two bytes long */
            ADB_DPRINTF("Invalid returned len for ADB register 3\n");
            return -1;
        case -1:
            /* ADB ERROR */
            ADB_DPRINTF("error gettting ADB register 3\n");
            return -1;
        }
    }

    fword("finish-device");

    return 0;
}

int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg,
             uint8_t *buf, int len)
{
    uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE];

    //ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len);
    if (dev->bus == NULL || dev->bus->req == NULL) {
        ADB_DPRINTF("ERROR: invalid bus !\n");
	for (;;);
    }
    /* Sanity checks */
    if (cmd != ADB_LISTEN && len != 0) {
        /* No buffer transmitted but for LISTEN command */
        ADB_DPRINTF("in buffer for cmd %d\n", cmd);
        return -1;
    }
    if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) {
        /* Need a buffer with a regular register size for LISTEN command */
        ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len);
        return -1;
    }
    if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) {
        /* Need a valid register number for LISTEN and TALK commands */
        ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg);
        return -1;
    }
    switch (cmd) {
    case ADB_SEND_RESET:
        adb_send[0] = ADB_SEND_RESET;
        break;
    case ADB_FLUSH:
        adb_send[0] = (dev->addr << 4) | ADB_FLUSH;
        break;
    case ADB_LISTEN:
        memcpy(adb_send + 1, buf, len);
        /* No break here */
    case ADB_TALK:
        adb_send[0] = (dev->addr << 4) | cmd | reg;
        break;
    }
    memset(adb_rcv, 0, ADB_BUF_SIZE);
    len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv);
#ifdef DEBUG_ADB
    //printk("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]);
#endif
    switch (len) {
    case 0:
        /* No data */
        break;
    case 2 ... 8:
        /* Register transmitted */
        if (buf != NULL)
            memcpy(buf, adb_rcv, len);
        break;
    default:
        /* Should never happen */
        //ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len);
        return -1;
    }
    //ADB_DPRINTF("retlen: %d\n", len);

    return len;
}
