18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
1228a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/qemu-file.h"
13e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
14f5bc01c356e1fa924ed07aadf589b3663873593eDavid 'Digit' Turner#include "hw/android/goldfish/device.h"
15f5bc01c356e1fa924ed07aadf589b3663873593eDavid 'Digit' Turner#include "hw/android/goldfish/vmem.h"
161365eb2b35736211464f313616e32f25569e5107David 'Digit' Turner#include "hw/hw.h"
171321c76d96910c2c807207f3fdfeb560c598ca60Jun Nakajima
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectenum {
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_PUT_CHAR       = 0x00,
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_BYTES_READY    = 0x04,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_CMD            = 0x08,
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_DATA_PTR       = 0x10,
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_DATA_LEN       = 0x14,
25d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    TTY_DATA_PTR_HIGH  = 0x18,
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_CMD_INT_DISABLE    = 0,
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_CMD_INT_ENABLE     = 1,
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_CMD_WRITE_BUFFER   = 2,
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TTY_CMD_READ_BUFFER    = 3,
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct tty_state {
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct goldfish_device dev;
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CharDriverState *cs;
36d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    uint64_t ptr;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t ptr_len;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t ready;
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t data[128];
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t data_count;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
43d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian#define  GOLDFISH_TTY_SAVE_VERSION  2
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  goldfish_tty_save(QEMUFile*  f, void*  opaque)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state*  s = opaque;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
49d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    qemu_put_be64( f, s->ptr );
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_put_be32( f, s->ptr_len );
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_put_byte( f, s->ready );
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_put_byte( f, s->data_count );
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_put_buffer( f, s->data, s->data_count );
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int  goldfish_tty_load(QEMUFile*  f, void*  opaque, int  version_id)
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state*  s = opaque;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
60d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    if ((version_id != GOLDFISH_TTY_SAVE_VERSION) &&
61d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian        (version_id != (GOLDFISH_TTY_SAVE_VERSION - 1))) {
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
63d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    }
64d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    if (version_id == (GOLDFISH_TTY_SAVE_VERSION - 1)) {
65d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian        s->ptr    = (uint64_t)qemu_get_be32(f);
66d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    } else {
67d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian        s->ptr    = qemu_get_be64(f);
68d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    }
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->ptr_len    = qemu_get_be32(f);
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->ready      = qemu_get_byte(f);
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->data_count = qemu_get_byte(f);
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_get_buffer(f, s->data, s->data_count);
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t goldfish_tty_read(void *opaque, hwaddr offset)
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state *s = (struct tty_state *)opaque;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    //printf("goldfish_tty_read %x %x\n", offset, size);
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (offset) {
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TTY_BYTES_READY:
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return s->data_count;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort (cpu_single_env, "goldfish_tty_read: Bad offset %x\n", offset);
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void goldfish_tty_write(void *opaque, hwaddr offset, uint32_t value)
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state *s = (struct tty_state *)opaque;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian    //printf("goldfish_tty_write %x %x %x\n", offset, value, size);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(offset) {
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TTY_PUT_CHAR: {
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint8_t ch = value;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if(s->cs)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                qemu_chr_write(s->cs, &ch, 1);
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } break;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TTY_CMD:
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch(value) {
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case TTY_CMD_INT_DISABLE:
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(s->ready) {
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if(s->data_count > 0)
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goldfish_device_set_irq(&s->dev, 0, 0);
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        s->ready = 0;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case TTY_CMD_INT_ENABLE:
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(!s->ready) {
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if(s->data_count > 0)
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goldfish_device_set_irq(&s->dev, 0, 1);
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        s->ready = 1;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case TTY_CMD_WRITE_BUFFER:
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(s->cs) {
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        int len;
126a1a2b3fded2d2797e6590c1b3a2c684c6ff9285dOctavian Purdila                        target_ulong  buf;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        buf = s->ptr;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        len = s->ptr_len;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        while (len) {
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            char   temp[64];
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            int    to_write = sizeof(temp);
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            if (to_write > len)
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                to_write = len;
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
137aaef275467ba13162d52ef6f690fd97f9733eb58David 'Digit' Turner                            safe_memory_rw_debug(current_cpu, buf, (uint8_t*)temp, to_write, 0);
1384e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                            qemu_chr_write(s->cs, (const uint8_t*)temp, to_write);
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            buf += to_write;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            len -= to_write;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
142d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian                        //printf("goldfish_tty_write: got %d bytes from %llx\n", s->ptr_len, (unsigned long long)s->ptr);
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case TTY_CMD_READ_BUFFER:
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(s->ptr_len > s->data_count)
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
149aaef275467ba13162d52ef6f690fd97f9733eb58David 'Digit' Turner                    safe_memory_rw_debug(current_cpu, s->ptr, s->data, s->ptr_len,1);
150d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian                    //printf("goldfish_tty_write: read %d bytes to %llx\n", s->ptr_len, (unsigned long long)s->ptr);
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(s->data_count > s->ptr_len)
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len);
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->data_count -= s->ptr_len;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if(s->data_count == 0 && s->ready)
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goldfish_device_set_irq(&s->dev, 0, 0);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            };
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TTY_DATA_PTR:
164d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian            uint64_set_low(&s->ptr, value);
165d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian            break;
166d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian
167d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian        case TTY_DATA_PTR_HIGH:
168d3ad7cd1206c25df2fafeb7e698ad2b46cb5cc24Jun Tian            uint64_set_high(&s->ptr, value);
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TTY_DATA_LEN:
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->ptr_len = value;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset);
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int tty_can_receive(void *opaque)
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state *s = opaque;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (sizeof(s->data) - s->data_count);
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tty_receive(void *opaque, const uint8_t *buf, int size)
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state *s = opaque;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy(s->data + s->data_count, buf, size);
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->data_count += size;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(s->data_count > 0 && s->ready)
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goldfish_device_set_irq(&s->dev, 0, 1);
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUReadMemoryFunc *goldfish_tty_readfn[] = {
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_read,
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_read,
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_read
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUWriteMemoryFunc *goldfish_tty_writefn[] = {
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_write,
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_write,
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_tty_write
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint goldfish_tty_add(CharDriverState *cs, int id, uint32_t base, int irq)
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tty_state *s;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static int  instance_id = 0;
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
215aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s = g_malloc0(sizeof(*s));
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.name = "goldfish_tty";
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.id = id;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.base = base;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.size = 0x1000;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.irq = irq;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dev.irq_count = 1;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->cs = cs;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(cs) {
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_chr_add_handlers(cs, tty_can_receive, tty_receive, NULL, s);
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = goldfish_device_add(&s->dev, goldfish_tty_readfn, goldfish_tty_writefn, s);
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(ret) {
230aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free(s);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
2325cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner        register_savevm(NULL,
2335cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        "goldfish_tty",
2345cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        instance_id++,
2355cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        GOLDFISH_TTY_SAVE_VERSION,
2365cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        goldfish_tty_save,
2375cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        goldfish_tty_load,
2385cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                        s);
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
243