Stand-alone SCI/SCIF emulation code, by Magnus Damm.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3270 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 9002da3..1028c5c 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -27,13 +27,6 @@
 #include "sh7750_regs.h"
 #include "sh7750_regnames.h"
 
-typedef struct {
-    uint8_t data[16];
-    uint8_t length;		/* Number of characters in the FIFO */
-    uint8_t write_idx;		/* Index of first character to write */
-    uint8_t read_idx;		/* Index of first character to read */
-} fifo;
-
 #define NB_DEVICES 4
 
 typedef struct SH7750State {
@@ -43,27 +36,6 @@
     uint32_t periph_freq;
     /* SDRAM controller */
     uint16_t rfcr;
-    /* First serial port */
-    CharDriverState *serial1;
-    uint8_t scscr1;
-    uint8_t scsmr1;
-    uint8_t scbrr1;
-    uint8_t scssr1;
-    uint8_t scssr1_read;
-    uint8_t sctsr1;
-    uint8_t sctsr1_loaded;
-    uint8_t sctdr1;
-    uint8_t scrdr1;
-    /* Second serial port */
-    CharDriverState *serial2;
-    uint16_t sclsr2;
-    uint16_t scscr2;
-    uint16_t scfcr2;
-    uint16_t scfsr2;
-    uint16_t scsmr2;
-    uint8_t scbrr2;
-    fifo serial2_receive_fifo;
-    fifo serial2_transmit_fifo;
     /* IO ports */
     uint16_t gpioic;
     uint32_t pctra;
@@ -84,263 +56,6 @@
 
 } SH7750State;
 
-/**********************************************************************
- First serial port
-**********************************************************************/
-
-static int serial1_can_receive(void *opaque)
-{
-    SH7750State *s = opaque;
-
-    return s->scscr1 & SH7750_SCSCR_RE;
-}
-
-static void serial1_receive_char(SH7750State * s, uint8_t c)
-{
-    if (s->scssr1 & SH7750_SCSSR1_RDRF) {
-	s->scssr1 |= SH7750_SCSSR1_ORER;
-	return;
-    }
-
-    s->scrdr1 = c;
-    s->scssr1 |= SH7750_SCSSR1_RDRF;
-}
-
-static void serial1_receive(void *opaque, const uint8_t * buf, int size)
-{
-    SH7750State *s = opaque;
-    int i;
-
-    for (i = 0; i < size; i++) {
-	serial1_receive_char(s, buf[i]);
-    }
-}
-
-static void serial1_event(void *opaque, int event)
-{
-    assert(0);
-}
-
-static void serial1_maybe_send(SH7750State * s)
-{
-    uint8_t c;
-
-    if (s->scssr1 & SH7750_SCSSR1_TDRE)
-	return;
-    c = s->sctdr1;
-    s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
-    if (s->scscr1 & SH7750_SCSCR_TIE) {
-	fprintf(stderr, "interrupts for serial port 1 not implemented\n");
-	assert(0);
-    }
-    /* XXXXX Check for errors in write */
-    qemu_chr_write(s->serial1, &c, 1);
-}
-
-static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value)
-{
-    uint8_t new_flags;
-
-    /* If transmit disable, TDRE and TEND stays up */
-    if ((s->scscr1 & SH7750_SCSCR_TE) == 0) {
-	mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
-    }
-
-    /* Only clear bits which have been read before and do not set any bit
-       in the flags */
-    new_flags = s->scssr1 & ~s->scssr1_read;	/* Preserve unread flags */
-    new_flags &= mem_value | ~s->scssr1_read;	/* Clear read flags */
-
-    s->scssr1 = (new_flags & 0xf8) | (mem_value & 1);
-    s->scssr1_read &= mem_value;
-
-    /* If TDRE has been cleared, TEND will also be cleared */
-    if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) {
-	s->scssr1 &= ~SH7750_SCSSR1_TEND;
-    }
-
-    /* Check for transmission to start */
-    serial1_maybe_send(s);
-}
-
-static void serial1_update_parameters(SH7750State * s)
-{
-    QEMUSerialSetParams ssp;
-
-    if (s->scsmr1 & SH7750_SCSMR_CHR_7)
-	ssp.data_bits = 7;
-    else
-	ssp.data_bits = 8;
-    if (s->scsmr1 & SH7750_SCSMR_PE) {
-	if (s->scsmr1 & SH7750_SCSMR_PM_ODD)
-	    ssp.parity = 'O';
-	else
-	    ssp.parity = 'E';
-    } else
-	ssp.parity = 'N';
-    if (s->scsmr1 & SH7750_SCSMR_STOP_2)
-	ssp.stop_bits = 2;
-    else
-	ssp.stop_bits = 1;
-    fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1);
-    ssp.speed = s->periph_freq /
-	(32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1;
-    fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
-	    ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
-    qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr1_changed(SH7750State * s)
-{
-    if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
-	if (!s->serial1) {
-	    fprintf(stderr, "serial port 1 not bound to anything\n");
-	    assert(0);
-	}
-	serial1_update_parameters(s);
-    }
-    if ((s->scscr1 & SH7750_SCSCR_RE) == 0) {
-	s->scssr1 |= SH7750_SCSSR1_TDRE;
-    }
-}
-
-static void init_serial1(SH7750State * s, int serial_nb)
-{
-    CharDriverState *chr;
-
-    s->scssr1 = 0x84;
-    chr = serial_hds[serial_nb];
-    if (!chr) {
-	fprintf(stderr,
-		"no serial port associated to SH7750 first serial port\n");
-	return;
-    }
-
-    s->serial1 = chr;
-    qemu_chr_add_handlers(chr, serial1_can_receive,
-			  serial1_receive, serial1_event, s);
-}
-
-/**********************************************************************
- Second serial port
-**********************************************************************/
-
-static int serial2_can_receive(void *opaque)
-{
-    SH7750State *s = opaque;
-    static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 };
-
-    return s->serial2_receive_fifo.length <
-	max_fifo_size[(s->scfcr2 >> 9) & 7];
-}
-
-static void serial2_adjust_receive_flags(SH7750State * s)
-{
-    static uint8_t max_fifo_size[] = { 1, 4, 8, 14 };
-
-    /* XXXXX Add interrupt generation */
-    if (s->serial2_receive_fifo.length >=
-	max_fifo_size[(s->scfcr2 >> 7) & 3]) {
-	s->scfsr2 |= SH7750_SCFSR2_RDF;
-	s->scfsr2 &= ~SH7750_SCFSR2_DR;
-    } else {
-	s->scfsr2 &= ~SH7750_SCFSR2_RDF;
-	if (s->serial2_receive_fifo.length > 0)
-	    s->scfsr2 |= SH7750_SCFSR2_DR;
-	else
-	    s->scfsr2 &= ~SH7750_SCFSR2_DR;
-    }
-}
-
-static void serial2_append_char(SH7750State * s, uint8_t c)
-{
-    if (s->serial2_receive_fifo.length == 16) {
-	/* Overflow */
-	s->sclsr2 |= SH7750_SCLSR2_ORER;
-	return;
-    }
-
-    s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c;
-    s->serial2_receive_fifo.length++;
-    serial2_adjust_receive_flags(s);
-}
-
-static void serial2_receive(void *opaque, const uint8_t * buf, int size)
-{
-    SH7750State *s = opaque;
-    int i;
-
-    for (i = 0; i < size; i++)
-	serial2_append_char(s, buf[i]);
-}
-
-static void serial2_event(void *opaque, int event)
-{
-    /* XXXXX */
-    assert(0);
-}
-
-static void serial2_update_parameters(SH7750State * s)
-{
-    QEMUSerialSetParams ssp;
-
-    if (s->scsmr2 & SH7750_SCSMR_CHR_7)
-	ssp.data_bits = 7;
-    else
-	ssp.data_bits = 8;
-    if (s->scsmr2 & SH7750_SCSMR_PE) {
-	if (s->scsmr2 & SH7750_SCSMR_PM_ODD)
-	    ssp.parity = 'O';
-	else
-	    ssp.parity = 'E';
-    } else
-	ssp.parity = 'N';
-    if (s->scsmr2 & SH7750_SCSMR_STOP_2)
-	ssp.stop_bits = 2;
-    else
-	ssp.stop_bits = 1;
-    fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2);
-    ssp.speed = s->periph_freq /
-	(32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1;
-    fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
-	    ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
-    qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr2_changed(SH7750State * s)
-{
-    if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
-	if (!s->serial2) {
-	    fprintf(stderr, "serial port 2 not bound to anything\n");
-	    assert(0);
-	}
-	serial2_update_parameters(s);
-    }
-}
-
-static void init_serial2(SH7750State * s, int serial_nb)
-{
-    CharDriverState *chr;
-
-    s->scfsr2 = 0x0060;
-
-    chr = serial_hds[serial_nb];
-    if (!chr) {
-	fprintf(stderr,
-		"no serial port associated to SH7750 second serial port\n");
-	return;
-    }
-
-    s->serial2 = chr;
-    qemu_chr_add_handlers(chr, serial2_can_receive,
-			  serial2_receive, serial1_event, s);
-}
-
-static void init_serial_ports(SH7750State * s)
-{
-    init_serial1(s, 0);
-    init_serial2(s, 1);
-}
 
 /**********************************************************************
  I/O ports
@@ -472,17 +187,7 @@
 
 static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
 {
-    SH7750State *s = opaque;
-    uint8_t r;
-
     switch (addr) {
-    case SH7750_SCSSR1_A7:
-	r = s->scssr1;
-	s->scssr1_read |= r;
-	return s->scssr1;
-    case SH7750_SCRDR1_A7:
-	s->scssr1 &= ~SH7750_SCSSR1_RDRF;
-	return s->scrdr1;
     default:
 	error_access("byte read", addr);
 	assert(0);
@@ -492,20 +197,12 @@
 static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
 {
     SH7750State *s = opaque;
-    uint16_t r;
 
     switch (addr) {
     case SH7750_RFCR_A7:
 	fprintf(stderr,
 		"Read access to refresh count register, incrementing\n");
 	return s->rfcr++;
-    case SH7750_SCLSR2_A7:
-	/* Read and clear overflow bit */
-	r = s->sclsr2;
-	s->sclsr2 = 0;
-	return r;
-    case SH7750_SCSFR2_A7:
-	return s->scfsr2;
     case SH7750_PDTRA_A7:
 	return porta_lines(s);
     case SH7750_PDTRB_A7:
@@ -554,34 +251,12 @@
 static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
 			      uint32_t mem_value)
 {
-    SH7750State *s = opaque;
-
     switch (addr) {
 	/* PRECHARGE ? XXXXX */
     case SH7750_PRECHARGE0_A7:
     case SH7750_PRECHARGE1_A7:
 	ignore_access("byte write", addr);
 	return;
-    case SH7750_SCBRR2_A7:
-	s->scbrr2 = mem_value;
-	return;
-    case SH7750_SCSCR1_A7:
-	s->scscr1 = mem_value;
-	scscr1_changed(s);
-	return;
-    case SH7750_SCSMR1_A7:
-	s->scsmr1 = mem_value;
-	return;
-    case SH7750_SCBRR1_A7:
-	s->scbrr1 = mem_value;
-	return;
-    case SH7750_SCTDR1_A7:
-	s->scssr1 &= ~SH7750_SCSSR1_TEND;
-	s->sctdr1 = mem_value;
-	return;
-    case SH7750_SCSSR1_A7:
-	serial1_change_scssr1(s, mem_value);
-	return;
     default:
 	error_access("byte write", addr);
 	assert(0);
@@ -596,8 +271,6 @@
 
     switch (addr) {
 	/* SDRAM controller */
-    case SH7750_SCBRR1_A7:
-    case SH7750_SCBRR2_A7:
     case SH7750_BCR2_A7:
     case SH7750_BCR3_A7:
     case SH7750_RTCOR_A7:
@@ -620,19 +293,6 @@
 	fprintf(stderr, "Write access to refresh count register\n");
 	s->rfcr = mem_value;
 	return;
-    case SH7750_SCLSR2_A7:
-	s->sclsr2 = mem_value;
-	return;
-    case SH7750_SCSCR2_A7:
-	s->scscr2 = mem_value;
-	scscr2_changed(s);
-	return;
-    case SH7750_SCFCR2_A7:
-	s->scfcr2 = mem_value;
-	return;
-    case SH7750_SCSMR2_A7:
-	s->scsmr2 = mem_value;
-	return;
     case SH7750_GPIOIC_A7:
 	s->gpioic = mem_value;
 	if (mem_value != 0) {
@@ -734,7 +394,10 @@
 					      sh7750_mem_read,
 					      sh7750_mem_write, s);
     cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
-    init_serial_ports(s);
+
+    sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]);
+    sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
+		   s->periph_freq, serial_hds[1]);
 
     tmu012_init(0x1fd80000,
 		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,