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