r1667 - in trunk/src/host/qemu-neo1973: . hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Fri Apr 6 01:51:01 CEST 2007


Author: andrew
Date: 2007-04-06 01:50:59 +0200 (Fri, 06 Apr 2007)
New Revision: 1667

Added:
   trunk/src/host/qemu-neo1973/hw/modem.c
Modified:
   trunk/src/host/qemu-neo1973/Makefile.target
   trunk/src/host/qemu-neo1973/hw/neo1973.c
   trunk/src/host/qemu-neo1973/vl.h
Log:
Add a dummy modem attached to UART0 (most functions unimplemented).
Clean-up the Neo board file.


Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target	2007-04-05 21:41:34 UTC (rev 1666)
+++ trunk/src/host/qemu-neo1973/Makefile.target	2007-04-05 23:50:59 UTC (rev 1667)
@@ -381,7 +381,7 @@
 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
 VL_OBJS+= ads7846.o sd.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
 VL_OBJS+= s3c2410.o s3c24xx_gpio.o s3c24xx_lcd.o s3c24xx_mmci.o s3c24xx_rtc.o
-VL_OBJS+= neo1973.o pcf5060x.o jbt6k74.o
+VL_OBJS+= neo1973.o pcf5060x.o jbt6k74.o modem.o
 CPPFLAGS += -DHAS_AUDIO -DHIGH_LATENCY
 endif
 ifeq ($(TARGET_BASE_ARCH), sh4)

Added: trunk/src/host/qemu-neo1973/hw/modem.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/modem.c	2007-04-05 21:41:34 UTC (rev 1666)
+++ trunk/src/host/qemu-neo1973/hw/modem.c	2007-04-05 23:50:59 UTC (rev 1667)
@@ -0,0 +1,447 @@
+/*
+ * AT commands interpreter. (Fake GSM modem)
+ *
+ * Copyright (c) 2007 OpenMoko, Inc.
+ * Author: Andrzej Zaborowski <andrew at openedhand.com>
+ *
+ * This code is licenced under the GNU GPL v2.
+ */
+#include "vl.h"
+
+struct modem_s {
+    int enable;
+    CharDriverState chr;
+    IOCanRWHandler *can_read;
+    IOReadHandler *read;
+    void *opaque;
+    int cmd_len;
+    char cmd[1024];
+#define FIFO_LEN	4096
+    int out_start;
+    int out_len;
+    char outfifo[FIFO_LEN];
+    QEMUTimer *out_tm;
+    int64_t baud_delay;
+};
+
+static void modem_reset(struct modem_s *s)
+{
+    s->cmd_len = 0;
+    s->out_len = 0;
+    s->baud_delay = ticks_per_sec;
+}
+
+static void modem_add_read_handler(CharDriverState *chr,
+                IOCanRWHandler *modem_can_read, IOReadHandler *modem_read,
+                void *opaque)
+{
+    struct modem_s *s = (struct modem_s *) chr->opaque;
+
+    s->can_read = modem_can_read;
+    s->read = modem_read;
+    s->opaque = opaque;
+}
+
+static inline void modem_fifo_wake(struct modem_s *s)
+{
+    if (!s->enable || !s->out_len)
+        return;
+
+    if (s->can_read && s->can_read(s->opaque) && s->read) {
+        s->read(s->opaque, s->outfifo + s->out_start ++, 1);
+        s->out_len --;
+        s->out_start &= FIFO_LEN - 1;
+    }
+
+    if (s->out_len)
+        qemu_mod_timer(s->out_tm, qemu_get_clock(vm_clock) + s->baud_delay);
+}
+
+static void modem_resp(struct modem_s *s, const char *fmt, ...)
+        __attribute__ ((__format__ (__printf__, 2, 3)));
+static void modem_resp(struct modem_s *s, const char *fmt, ...)
+{
+    static char buf[FIFO_LEN];
+    int len, off;
+    va_list ap;
+    va_start(ap, fmt);
+    len = vsnprintf(buf, sizeof(buf), fmt, ap);
+    va_end(ap);
+    if (len + s->out_len > FIFO_LEN) {
+        s->out_len = 0;
+        return;
+    }
+    off = (s->out_start + s->out_len) & (FIFO_LEN - 1);
+    if (off + len > FIFO_LEN) {
+        memcpy(s->outfifo + off, buf, FIFO_LEN - off);
+        memcpy(s->outfifo, buf + (FIFO_LEN - off), off + len - FIFO_LEN);
+    } else
+        memcpy(s->outfifo + off, buf, len);
+    s->out_len += len;
+    modem_fifo_wake(s);
+}
+
+static struct modem_cmd_s {
+    const char *cmd;
+    enum { modem_ok, modem_error, modem_call, modem_str } action;
+    int (*call)(struct modem_s *s, const char *param);
+    const char *resp;
+} modem_cmds[] = {
+    { "AT+CACM", modem_error },
+    { "AT+CAMM", modem_error },
+    { "AT+CAOC", modem_error },
+    { "AT+CBC", modem_error },
+    { "AT+CBST", modem_error },
+    { "AT+CCFC", modem_error },
+    { "AT+CCUG", modem_error },
+    { "AT+CCWA", modem_error },
+    { "AT+CCWE", modem_error },
+    { "AT+CEER", modem_error },
+    { "AT+CFUN", modem_error },
+    { "AT+CGACT", modem_error },
+    { "AT+CGANS", modem_error },
+    { "AT+CGATT", modem_error },
+    { "AT+CGAUTO", modem_error },
+    { "AT+CGCLASS", modem_error },
+    { "AT+CGDATA", modem_error },
+    { "AT+CGDCONT", modem_error },
+    { "AT+CGEREP", modem_error },
+    { "AT+CGMI", modem_str, 0, "<manufacturer>\n\n" },
+    { "AT+CGMM", modem_str, 0, "<model>\n\n" },
+    { "AT+CGMR", modem_str, 0, "<revision>\n\n" },
+    { "AT+CGPADDR", modem_error },
+    { "AT+CGQMIN", modem_error },
+    { "AT+CGQREQ", modem_error },
+    { "AT+CGREG", modem_error },
+    { "AT+CGSMS", modem_error },
+    { "AT+CGSN", modem_str, 0, "<serial number>\n\n" },
+    { "AT+CHLD", modem_error },
+    { "AT+CHUP", modem_error },
+    { "AT+CIMI", modem_error },
+    { "AT+CLAC", modem_error },
+    { "AT+CLAE", modem_error },
+    { "AT+CLAN", modem_error },
+    { "AT+CLCC", modem_error },
+    { "AT+CLCK", modem_error },
+    { "AT+CLIP", modem_error },
+    { "AT+CDIP", modem_error },
+    { "AT+CLIR", modem_error },
+    { "AT+CLVL", modem_error },
+    { "AT+CMEE", modem_error },
+    { "AT+CMGC", modem_error },
+    { "AT+CMGD", modem_error },
+    { "AT+CMGF", modem_error },
+    { "AT+CMGL", modem_error },
+    { "AT+CMGR", modem_error },
+    { "AT+CMGS", modem_error },
+    { "AT+CMGW", modem_error },
+    { "AT+CMOD", modem_error },
+    { "AT+CMSS", modem_error },
+    { "AT+CMMS", modem_error },
+    { "AT+CMUT", modem_error },
+    { "AT+CMUX", modem_error },
+    { "AT+CNMA", modem_error },
+    { "AT+CNMI", modem_error },
+    { "AT+CNUM", modem_error },
+    { "AT+COLP", modem_error },
+    { "AT+COPN", modem_error },
+    { "AT+COPS", modem_ok },
+    { "AT+CPAS", modem_error },
+    { "AT+CPBF", modem_error },
+    { "AT+CPBR", modem_error },
+    { "AT+CPBS", modem_error },
+    { "AT+CPBW", modem_error },
+    { "AT+CPIN", modem_ok },
+    { "AT+CPMS", modem_error },
+    { "AT+CPOL", modem_error },
+    { "AT+CPUC", modem_error },
+    { "AT+CPWD", modem_error },
+    { "AT+CR", modem_error },
+    { "AT+CRC", modem_error },
+    { "AT+CREG", modem_error },
+    { "AT+CRES", modem_error },
+    { "AT+CRLP", modem_error },
+    { "AT+CRSL", modem_error },
+    { "AT+CRSM", modem_error },
+    { "AT+CSAS", modem_error },
+    { "AT+CSCA", modem_error },
+    { "AT+CSCB", modem_error },
+    { "AT+CSCS", modem_error },
+    { "AT+CSDH", modem_error },
+    { "AT+CSIM", modem_error },
+    { "AT+CSMP", modem_error },
+    { "AT+CSMS", modem_error },
+    { "AT+CSNS", modem_error },
+    { "AT+CSQ", modem_error },
+    { "AT%CSQ", modem_error },
+    { "AT+CSSN", modem_error },
+    { "AT+CSTA", modem_error },
+    { "AT+CSVM", modem_error },
+    { "AT+CTFR", modem_error },
+    { "AT+CUSD", modem_error },
+    { "AT+DR", modem_error },
+    { "AT+FAP", modem_error },
+    { "AT+FBO", modem_error },
+    { "AT+FBS", modem_error },
+    { "AT+FBU", modem_error },
+    { "AT+FCC", modem_error },
+    { "AT+FCLASS", modem_error },
+    { "AT+FCQ", modem_error },
+    { "AT+FCR", modem_error },
+    { "AT+FCS", modem_error },
+    { "AT+FCT", modem_error },
+    { "AT+FDR", modem_error },
+    { "AT+FDT", modem_error },
+    { "AT+FEA", modem_error },
+    { "AT+FFC", modem_error },
+    { "AT+FHS", modem_error },
+    { "AT+FIE", modem_error },
+    { "AT+FIP", modem_error },
+    { "AT+FIS", modem_error },
+    { "AT+FIT", modem_error },
+    { "AT+FKS", modem_error },
+    { "AT+FLI", modem_error },
+    { "AT+FLO", modem_error },
+    { "AT+FLP", modem_error },
+    { "AT+FMI", modem_error },
+    { "AT+FMM", modem_error },
+    { "AT+FMR", modem_error },
+    { "AT+FMS", modem_error },
+    { "AT+FND", modem_error },
+    { "AT+FNR", modem_error },
+    { "AT+FNS", modem_error },
+    { "AT+FPA", modem_error },
+    { "AT+FPI", modem_error },
+    { "AT+FPS", modem_error },
+    { "AT+FPW", modem_error },
+    { "AT+FRQ", modem_error },
+    { "AT+FSA", modem_error },
+    { "AT+FSP", modem_error },
+    { "AT+GCAP", modem_error },
+    { "AT+GCI", modem_error },
+    { "AT+GMI", modem_error },
+    { "AT+GMM", modem_error },
+    { "AT+GMR", modem_error },
+    { "AT+GSN", modem_error },
+    { "AT+ICF", modem_error },
+    { "AT+IFC", modem_error },
+    { "AT+ILRR", modem_error },
+    { "AT+IPR", modem_error },
+    { "AT+VTS", modem_error },
+    { "AT+WS46", modem_error },
+    { "AT%ALS", modem_error },
+    { "AT%ATR", modem_error },
+    { "AT%BAND", modem_error },
+    { "AT%CACM", modem_error },
+    { "AT%CAOC", modem_error },
+    { "AT%CCBS", modem_error },
+    { "AT%STDR", modem_error },
+    { "AT%CGAATT", modem_error },
+    { "AT%CGMM", modem_error },
+    { "AT%CGREG", modem_error },
+    { "AT%CNAP", modem_error },
+    { "AT%CPI", modem_error },
+    { "AT%COLR", modem_error },
+    { "AT%CPRIM", modem_error },
+    { "AT%CTV", modem_error },
+    { "AT%CUNS", modem_error },
+    { "AT%NRG", modem_error },
+    { "AT%SATC", modem_error },
+    { "AT%SATE", modem_error },
+    { "AT%SATR", modem_error },
+    { "AT%SATT", modem_error },
+    { "AT%SNCNT", modem_error },
+    { "AT%VER", modem_error },
+    { "AT%CGCLASS", modem_error },
+    { "AT%CGPCO", modem_error },
+    { "AT%CGPPP", modem_error },
+    { "AT%EM", modem_error },
+    { "AT%EMET", modem_error },
+    { "AT%EMETS", modem_error },
+    { "AT%CBHZ", modem_error },
+    { "AT%CPHS", modem_error },
+    { "AT%CPNUMS", modem_error },
+    { "AT%CPALS", modem_error },
+    { "AT%CPVWI", modem_error },
+    { "AT%CPOPN", modem_error },
+    { "AT%CPCFU", modem_error },
+    { "AT%CPINF", modem_error },
+    { "AT%CPMB", modem_error },
+    { "AT%CPRI", modem_error },
+    { "AT%DATA", modem_error },
+    { "AT%DINF", modem_error },
+    { "AT%CLCC", modem_error },
+    { "AT%DBGINFO", modem_error },
+    { "AT%VTS", modem_error },
+    { "AT%CHPL", modem_error },
+    { "AT%CREG", modem_error },
+    { "AT+CTZR", modem_error },
+    { "AT+CTZU", modem_error },
+    { "AT%CTZV", modem_error },
+    { "AT%CNIV", modem_error },
+    { "AT%PVRF", modem_error },
+    { "AT%CWUP", modem_error },
+    { "AT%DAR", modem_error },
+    { "AT+CIND", modem_error },
+    { "AT+CMER", modem_error },
+    { "AT%CSCN", modem_error },
+    { "AT%RDL", modem_error },
+    { "AT%RDLB", modem_error },
+    { "AT%CSTAT", modem_error },
+    { "AT%CPRSM", modem_error },
+    { "AT%CHLD", modem_error },
+    { "AT%SIMIND", modem_error },
+    { "AT%SECP", modem_error },
+    { "AT%SECS", modem_error },
+    { "AT%CSSN", modem_error },
+    { "AT+CCLK", modem_error },
+    { "AT%CSSD", modem_error },
+    { "AT%COPS", modem_error },
+    { "AT%CPMBW", modem_error },
+    { "AT%CUST", modem_error },
+    { "AT%SATCC", modem_error },
+    { "AT%COPN", modem_error },
+    { "AT%CGEREP", modem_error },
+    { "AT%CUSCFG", modem_error },
+    { "AT%CUSDR", modem_error },
+    { "AT%CPBS", modem_error },
+    { "AT%PBCF", modem_error },
+    { "AT%SIMEF", modem_error },
+    { "AT%EFRSLT", modem_error },
+    { "AT%CMGMDU", modem_error },
+    { "AT%CMGL", modem_error },
+    { "AT%CMGR", modem_error },
+    { "ATA", modem_ok },
+    { "ATB", modem_error },
+    { "AT&C", modem_error },
+    { "ATD", modem_ok },
+    { "AT&D", modem_error },
+    { "ATE", modem_ok },
+    { "ATF", modem_error },
+    { "AT&F", modem_error },
+    { "ATH", modem_ok },
+    { "ATI", modem_error },
+    { "AT&K", modem_error },
+    { "ATL", modem_error },
+    { "ATM", modem_error },
+    { "ATO", modem_error },
+    { "ATP", modem_error },
+    { "ATQ", modem_error },
+    { "ATS", modem_error },
+    { "ATT", modem_error },
+    { "ATV", modem_error },
+    { "ATW", modem_error },
+    { "AT&W", modem_error },
+    { "ATX", modem_error },
+    { "ATZ", modem_error },
+    { 0 }
+};
+
+static void modem_cmd(struct modem_s *s, const char *cmd)
+{
+    struct modem_cmd_s *entry;
+    const char *eq, *param;
+    int ok;
+    eq = strchr(cmd, '=');
+    if (eq)
+        param = eq + 1;
+    else
+        param = 0;
+    ok = 0;
+    for (entry = modem_cmds; entry->cmd; entry ++)
+        if (!strncmp(cmd, entry->cmd, strlen(entry->cmd))) {
+            switch (entry->action) {
+            case modem_ok:
+                ok = 1;
+                break;
+            case modem_error:
+                ok = 0;
+                break;
+            case modem_call:
+                ok = entry->call(s, param);
+                break;
+            case modem_str:
+                modem_resp(s, entry->resp);
+                ok = 1;
+                break;
+            }
+            return;
+        }
+    if (ok)
+        modem_resp(s, "OK\n");
+    else
+        modem_resp(s, "ERROR\n");
+}
+
+static int modem_write(struct CharDriverState *chr,
+                const uint8_t *buf, int len)
+{
+    struct modem_s *s = (struct modem_s *) chr->opaque;
+    char *eol;
+    if (!s->enable)
+        return 0;
+
+    len = MIN(len, 1023 - s->cmd_len);
+    memcpy(s->cmd + s->cmd_len, buf, len);
+    s->cmd_len += len;
+    s->cmd[s->cmd_len] = 0;
+
+    eol = strchr(s->cmd, '\n');
+    if (eol) {
+        s->cmd_len -= eol - s->cmd;
+        *eol = 0;
+        modem_cmd(s, s->cmd);
+        memcpy(s->cmd, eol + 1, s->cmd_len --);
+    } else if (s->cmd_len >= 1023)
+        s->cmd_len = 0;
+    return len;
+}
+
+static int modem_ioctl(struct CharDriverState *chr, int cmd, void *arg)
+{
+    QEMUSerialSetParams *ssp;
+    struct modem_s *s = (struct modem_s *) chr->opaque;
+    switch (cmd) {
+    case CHR_IOCTL_SERIAL_SET_PARAMS:
+        ssp = (QEMUSerialSetParams *) arg;
+        s->baud_delay = ticks_per_sec / ssp->speed;
+        break;
+
+    case CHR_IOCTL_MODEM_HANDSHAKE:
+        if (!s->enable)
+            return -ENOTSUP;
+        if (*(int *) arg)
+            modem_resp(s, "AT-Command Interpreter Ready\nOK\n");
+        break;
+
+    default:
+        return -ENOTSUP;
+    }
+    return 0;
+}
+
+void modem_enable(CharDriverState *chr, int enable)
+{
+    struct modem_s *s = (struct modem_s *) chr->opaque;
+    if (enable)
+        modem_reset(s);
+    s->enable = enable;
+}
+
+static void modem_out_tick(void *opaque)
+{
+    modem_fifo_wake((struct modem_s *) opaque);
+}
+
+CharDriverState *modem_init()
+{
+    struct modem_s *s = (struct modem_s *)
+            qemu_mallocz(sizeof(struct modem_s));
+    s->chr.opaque = s;
+    s->chr.chr_write = modem_write;
+    s->chr.chr_ioctl = modem_ioctl;
+    s->chr.chr_add_read_handler = modem_add_read_handler;
+    s->out_tm = qemu_new_timer(vm_clock, modem_out_tick, s);
+
+    return &s->chr;
+}

Modified: trunk/src/host/qemu-neo1973/hw/neo1973.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-04-05 21:41:34 UTC (rev 1666)
+++ trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-04-05 23:50:59 UTC (rev 1667)
@@ -54,6 +54,15 @@
 #define GTA01_GPIO_GPS_EN_3V	S3C_GPG(10)
 #define GTA01_GPIO_GPS_RESET	S3C_GPC(0)
 
+struct neo_board_s {
+    struct s3c_state_s *cpu;
+    struct i2c_slave_s *pmu;
+    struct i2c_slave_s *wm;
+    struct i2c_slave_s *lcm;
+    CharDriverState *modem;
+    void *kbd_pic;
+};
+
 /* Handlers for output ports */
 static void neo_bl_switch(int line, int level, void *opaque)
 {
@@ -84,6 +93,8 @@
 
 static void neo_modem_switch(int line, int level, void *opaque)
 {
+    struct neo_board_s *s = (struct neo_board_s *) opaque;
+    modem_enable(s->modem, level);
     neo_printf("Modem powered %s.\n", level ? "up" : "down");
 }
 
@@ -135,70 +146,62 @@
 {
 }
 
-struct neo_kbd_s {
-    void *pic;
-    struct i2c_slave_s *pmu;
-};
-
 /* Hardware keys */
 static void neo_kbd_handler(void *opaque, int keycode)
 {
-    struct neo_kbd_s *kbd = (struct neo_kbd_s *) opaque;
+    struct neo_board_s *s = (struct neo_board_s *) opaque;
     switch (keycode & 0x7f) {
     case 0x1c:	/* Return */
-        pic_set_irq_new(kbd->pic, GTA01_IRQ_911_KEY, !(keycode & 0x80));
+        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_911_KEY, !(keycode & 0x80));
         break;
     case 0x39:	/* Space */
-        pic_set_irq_new(kbd->pic, GTA01_IRQ_HOLD_KEY, !(keycode & 0x80));
-        pcf_onkey_set(kbd->pmu, !(keycode & 80));	/* Active LOW */
+        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_HOLD_KEY, !(keycode & 0x80));
+        pcf_onkey_set(s->pmu, !(keycode & 80));	/* Active LOW */
         break;
     }
 }
 
-static void neo_kbd_init(struct s3c_state_s *cpu, struct i2c_slave_s *pmu)
+static void neo_kbd_init(struct neo_board_s *s)
 {
-    struct neo_kbd_s *kbd = (struct neo_kbd_s *)
-            qemu_mallocz(sizeof(struct neo_kbd_s));
-    kbd->pic = cpu->io;
-    kbd->pmu = pmu;
-    qemu_add_kbd_event_handler(neo_kbd_handler, kbd);
+    s->kbd_pic = s->cpu->io;
+    qemu_add_kbd_event_handler(neo_kbd_handler, s);
 }
 
-static void neo_gpio_setup(struct s3c_state_s *cpu)
+static void neo_gpio_setup(struct neo_board_s *s)
 {
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_BACKLIGHT,
-                    neo_bl_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_GPS_PWRON,
-                    neo_gpspwr_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_MODEM_RST,
-                    neo_modem_rst_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_MODEM_ON,
-                    neo_modem_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_LCD_RESET,
-                    neo_lcd_rst_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_VIBRATOR_ON,
-                    neo_vib_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_VIBRATOR_ON2,
-                    neo_vib_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01v3_GPIO_nGSM_EN,
-                    neo_gsm_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01Bv2_GPIO_nGSM_EN,
-                    neo_gsm_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_BT_EN,
-                    neo_bt_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_GPS_EN_2V8,
-                    neo_gps_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_GPS_EN_3V,
-                    neo_gps_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_GPS_EN_3V3,
-                    neo_gps_switch, cpu);
-    s3c_gpio_handler_set(cpu->io, GTA01_GPIO_GPS_RESET,
-                    neo_gps_rst_switch, cpu);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BACKLIGHT,
+                    neo_bl_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_PWRON,
+                    neo_gpspwr_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_RST,
+                    neo_modem_rst_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_ON,
+                    neo_modem_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_LCD_RESET,
+                    neo_lcd_rst_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON,
+                    neo_vib_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON2,
+                    neo_vib_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01v3_GPIO_nGSM_EN,
+                    neo_gsm_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01Bv2_GPIO_nGSM_EN,
+                    neo_gsm_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BT_EN,
+                    neo_bt_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_2V8,
+                    neo_gps_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V,
+                    neo_gps_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V3,
+                    neo_gps_switch, s);
+    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_RESET,
+                    neo_gps_rst_switch, s);
 
-    s3c_timers_cmp_handler_set(cpu->timers, 0, neo_bl_intensity, cpu);
+    s3c_timers_cmp_handler_set(s->cpu->timers, 0, neo_bl_intensity, s);
 
     /* MMC/SD host */
-    s3c_mmci_handlers(cpu->mmci, cpu->io, neo_mmc_writeprotect_switch,
+    s3c_mmci_handlers(s->cpu->mmci, s->cpu->io, neo_mmc_writeprotect_switch,
                     neo_mmc_cover_switch);
 }
 
@@ -264,58 +267,62 @@
 #define NEO_WM_ADDR	0x1a
 #define NEO_AMP_ADDR	0x7c	/* ADR wired to low */
 
-static struct i2c_slave_s *neo_i2c_setup(struct s3c_state_s *cpu)
+static void neo_i2c_setup(struct neo_board_s *s)
 {
     struct i2c_bus_s *bus = (struct i2c_bus_s *)
             qemu_mallocz(sizeof(struct i2c_bus_s));
-    struct i2c_slave_s *pmu;
 #ifdef HAS_AUDIO
-    struct i2c_slave_s *wm;
     AudioState *audio;
 #endif
 
-    pmu = pcf5060x_init(cpu->pic, GTA01_IRQ_PCF50606, 0);
+    s->pmu = pcf5060x_init(s->cpu->pic, GTA01_IRQ_PCF50606, 0);
+    s->lcm = lm4857_init();
 
     /* Attach the CPU on one end of our I2C bus.  */
-    i2c_master_attach(bus, s3c_i2c_master(cpu->i2c));
+    i2c_master_attach(bus, s3c_i2c_master(s->cpu->i2c));
 
     /* Attach a PCF50606 to the bus */
-    i2c_slave_attach(bus, NEO_PMU_ADDR, pmu);
+    i2c_slave_attach(bus, NEO_PMU_ADDR, s->pmu);
 
     /* Attach a LM4857 to the bus */
-    i2c_slave_attach(bus, NEO_AMP_ADDR, lm4857_init());
+    i2c_slave_attach(bus, NEO_AMP_ADDR, s->lcm);
 
 #ifdef HAS_AUDIO
     audio = AUD_init();
     if (!audio)
-        goto done;
-    wm = wm8753_init(audio);
+        return;
+    s->wm = wm8753_init(audio);
 
     /* Attach a WM8750 to the bus */
-    i2c_slave_attach(bus, NEO_WM_ADDR, wm);
+    i2c_slave_attach(bus, NEO_WM_ADDR, s->wm);
     /* .. and to the sound interface.  */
-    cpu->i2s->opaque = wm->opaque;
-    cpu->i2s->codec_out = wm8753_dac_dat;
-    cpu->i2s->codec_in = wm8753_adc_dat;
-    wm8753_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
-done:
+    s->cpu->i2s->opaque = s->wm->opaque;
+    s->cpu->i2s->codec_out = wm8753_dac_dat;
+    s->cpu->i2s->codec_in = wm8753_adc_dat;
+    wm8753_data_req_set(s->wm, s->cpu->i2s->data_req, s->cpu->i2s);
 #endif
-    return pmu;
 }
 
-static void neo_spi_setup(struct s3c_state_s *cpu)
+static void neo_spi_setup(struct neo_board_s *s)
 {
     void *jbt6k74 = jbt6k74_init();
 
-    s3c_spi_attach(cpu->spi, 0, 0, 0, 0);
-    s3c_spi_attach(cpu->spi, 1, jbt6k74_txrx, jbt6k74_btxrx, jbt6k74);
+    s3c_spi_attach(s->cpu->spi, 0, 0, 0, 0);
+    s3c_spi_attach(s->cpu->spi, 1, jbt6k74_txrx, jbt6k74_btxrx, jbt6k74);
 }
 
+static void neo_gsm_setup(struct neo_board_s *s)
+{
+    s->modem = modem_init();
+
+    s3c_uart_attach(s->cpu->uart[0], s->modem);
+}
+
 static void neo_reset(void *opaque)
 {
-    struct s3c_state_s *cpu = (struct s3c_state_s *) opaque;
-    s3c2410_reset(cpu);
-    cpu->env->regs[15] = S3C_RAM_BASE;
+    struct neo_board_s *s = (struct neo_board_s *) opaque;
+    s3c2410_reset(s->cpu);
+    s->cpu->env->regs[15] = S3C_RAM_BASE;
 }
 
 /* Board init.  */
@@ -325,34 +332,36 @@
                 const char *initrd_filename)
 {
     uint32_t neo_ram = 0x08000000;
-    struct s3c_state_s *cpu;
-    struct i2c_slave_s *pmu;
+    struct neo_board_s *s = (struct neo_board_s *)
+            qemu_mallocz(sizeof(struct neo_board_s));
 
-    cpu = s3c2410_init(ds);
+    s->cpu = s3c2410_init(ds);
 
     /* Setup memory */
-    if (ram_size < neo_ram + cpu->free_ram_start) {
+    if (ram_size < neo_ram + s->cpu->free_ram_start) {
         fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        neo_ram + cpu->free_ram_start);
+                        neo_ram + s->cpu->free_ram_start);
         exit(1);
     }
     cpu_register_physical_memory(S3C_RAM_BASE, neo_ram,
-                    cpu->free_ram_start | IO_MEM_RAM);
-    cpu->free_ram_start += neo_ram;
+                    s->cpu->free_ram_start | IO_MEM_RAM);
+    s->cpu->free_ram_start += neo_ram;
 
-    s3c_nand_register(cpu, nand_init(NAND_MFR_SAMSUNG, 0x76));
+    s3c_nand_register(s->cpu, nand_init(NAND_MFR_SAMSUNG, 0x76));
 
     /* Setup peripherals */
-    neo_gpio_setup(cpu);
+    neo_gpio_setup(s);
 
-    pmu = neo_i2c_setup(cpu);
+    neo_i2c_setup(s);
 
-    neo_kbd_init(cpu, pmu);
+    neo_kbd_init(s);
 
-    neo_spi_setup(cpu);
+    neo_spi_setup(s);
 
-    qemu_register_reset(neo_reset, cpu);
+    neo_gsm_setup(s);
 
+    qemu_register_reset(neo_reset, s);
+
     /* Setup initial (reset) machine state */
 #if 0
     cpu->env->regs[15] = S3C_SRAM_BASE;
@@ -364,14 +373,14 @@
                     phys_ram_base + S3C_SRAM_SIZE + 0x03f80000);
     load_image(kernel_filename,
                     phys_ram_base + S3C_SRAM_SIZE + 0x02000000);
-    cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000;
+    s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000;
 #endif
 
     /* Imitate ONKEY wakeup */
-    pcf_onkey_set(pmu, 0);
-    pcf_onkey_set(pmu, 1);
+    pcf_onkey_set(s->pmu, 0);
+    pcf_onkey_set(s->pmu, 1);
     /* Connect the charger */
-    pcf_exton_set(pmu, 1);
+    pcf_exton_set(s->pmu, 1);
 }
 
 QEMUMachine neo1973_machine = {

Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h	2007-04-05 21:41:34 UTC (rev 1666)
+++ trunk/src/host/qemu-neo1973/vl.h	2007-04-05 23:50:59 UTC (rev 1667)
@@ -292,7 +292,7 @@
 #define CHR_IOCTL_PP_WRITE_CONTROL    6
 #define CHR_IOCTL_PP_READ_STATUS      7
 
-#define CHR_IOCTL_MODEM_SET_AFC       8
+#define CHR_IOCTL_MODEM_HANDSHAKE     8
 
 typedef void IOEventHandler(void *opaque, int event);
 
@@ -1462,6 +1462,10 @@
 #include "hw/s3c.h"
 #endif
 
+/* modem.c */
+CharDriverState *modem_init();
+void modem_enable(CharDriverState *chr, int enable);
+
 #endif /* defined(QEMU_TOOL) */
 
 /* monitor.c */





More information about the commitlog mailing list