symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/etraxfs_ser.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU ETRAX System Emulator
       
     3  *
       
     4  * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 
       
    25 #include <stdio.h>
       
    26 #include <ctype.h>
       
    27 #include "hw.h"
       
    28 #include "qemu-char.h"
       
    29 
       
    30 #define D(x)
       
    31 
       
    32 #define RW_TR_CTRL     0x00
       
    33 #define RW_TR_DMA_EN   0x04
       
    34 #define RW_REC_CTRL    0x08
       
    35 #define RW_DOUT        0x1c
       
    36 #define RS_STAT_DIN    0x20
       
    37 #define R_STAT_DIN     0x24
       
    38 #define RW_INTR_MASK   0x2c
       
    39 #define RW_ACK_INTR    0x30
       
    40 #define R_INTR         0x34
       
    41 #define R_MASKED_INTR  0x38
       
    42 
       
    43 #define STAT_DAV     16
       
    44 #define STAT_TR_IDLE 22
       
    45 #define STAT_TR_RDY  24
       
    46 
       
    47 struct etrax_serial_t
       
    48 {
       
    49 	CPUState *env;
       
    50 	CharDriverState *chr;
       
    51 	qemu_irq *irq;
       
    52 
       
    53 	int pending_tx;
       
    54 
       
    55 	/* Control registers.  */
       
    56 	uint32_t rw_tr_ctrl;
       
    57 	uint32_t rw_tr_dma_en;
       
    58 	uint32_t rw_rec_ctrl;
       
    59 	uint32_t rs_stat_din;
       
    60 	uint32_t r_stat_din;
       
    61 	uint32_t rw_intr_mask;
       
    62 	uint32_t rw_ack_intr;
       
    63 	uint32_t r_intr;
       
    64 	uint32_t r_masked_intr;
       
    65 };
       
    66 
       
    67 static void ser_update_irq(struct etrax_serial_t *s)
       
    68 {
       
    69 	uint32_t o_irq = s->r_masked_intr;
       
    70 
       
    71 	s->r_intr &= ~(s->rw_ack_intr);
       
    72 	s->r_masked_intr = s->r_intr & s->rw_intr_mask;
       
    73 
       
    74 	if (o_irq != s->r_masked_intr) {
       
    75 		D(printf("irq_mask=%x r_intr=%x rmi=%x airq=%x \n", 
       
    76 			 s->rw_intr_mask, s->r_intr, 
       
    77 			 s->r_masked_intr, s->rw_ack_intr));
       
    78 		if (s->r_masked_intr)
       
    79 			qemu_irq_raise(s->irq[0]);
       
    80 		else
       
    81 			qemu_irq_lower(s->irq[0]);
       
    82 	}
       
    83 	s->rw_ack_intr = 0;
       
    84 }
       
    85 
       
    86 
       
    87 static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
       
    88 {
       
    89 	D(CPUState *env = opaque);
       
    90 	D(printf ("%s %x\n", __func__, addr));
       
    91 	return 0;
       
    92 }
       
    93 
       
    94 static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
       
    95 {
       
    96 	struct etrax_serial_t *s = opaque;
       
    97 	D(CPUState *env = s->env);
       
    98 	uint32_t r = 0;
       
    99 
       
   100 	switch (addr)
       
   101 	{
       
   102 		case RW_TR_CTRL:
       
   103 			r = s->rw_tr_ctrl;
       
   104 			break;
       
   105 		case RW_TR_DMA_EN:
       
   106 			r = s->rw_tr_dma_en;
       
   107 			break;
       
   108 		case RS_STAT_DIN:
       
   109 			r = s->rs_stat_din;
       
   110 			/* clear dav.  */
       
   111 			s->rs_stat_din &= ~(1 << STAT_DAV);
       
   112 			break;
       
   113 		case R_STAT_DIN:
       
   114 			r = s->rs_stat_din;
       
   115 			break;
       
   116 		case RW_ACK_INTR:
       
   117 			D(printf("load rw_ack_intr=%x\n", s->rw_ack_intr));
       
   118 			r = s->rw_ack_intr;
       
   119 			break;
       
   120 		case RW_INTR_MASK:
       
   121 			r = s->rw_intr_mask;
       
   122 			break;
       
   123 		case R_INTR:
       
   124 			D(printf("load r_intr=%x\n", s->r_intr));
       
   125 			r = s->r_intr;
       
   126 			break;
       
   127 		case R_MASKED_INTR:
       
   128 			D(printf("load r_maked_intr=%x\n", s->r_masked_intr));
       
   129 			r = s->r_masked_intr;
       
   130 			break;
       
   131 
       
   132 		default:
       
   133 			D(printf ("%s %x\n", __func__, addr));
       
   134 			break;
       
   135 	}
       
   136 	return r;
       
   137 }
       
   138 
       
   139 static void
       
   140 ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
       
   141 {
       
   142 	D(struct etrax_serial_t *s = opaque);
       
   143 	D(CPUState *env = s->env);
       
   144  	D(printf ("%s %x %x\n", __func__, addr, value));
       
   145 }
       
   146 static void
       
   147 ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
       
   148 {
       
   149 	struct etrax_serial_t *s = opaque;
       
   150 	unsigned char ch = value;
       
   151 	D(CPUState *env = s->env);
       
   152 
       
   153 	switch (addr)
       
   154 	{
       
   155 		case RW_TR_CTRL:
       
   156 			D(printf("rw_tr_ctrl=%x\n", value));
       
   157 			s->rw_tr_ctrl = value;
       
   158 			break;
       
   159 		case RW_TR_DMA_EN:
       
   160 			D(printf("rw_tr_dma_en=%x\n", value));
       
   161 			s->rw_tr_dma_en = value;
       
   162 			break;
       
   163 		case RW_DOUT:
       
   164 			qemu_chr_write(s->chr, &ch, 1);
       
   165 			s->r_intr |= 1;
       
   166 			s->pending_tx = 1;
       
   167 			break;
       
   168 		case RW_ACK_INTR:
       
   169 			D(printf("rw_ack_intr=%x\n", value));
       
   170 			s->rw_ack_intr = value;
       
   171 			if (s->pending_tx && (s->rw_ack_intr & 1)) {
       
   172 				s->r_intr |= 1;
       
   173 				s->pending_tx = 0;
       
   174 				s->rw_ack_intr &= ~1;
       
   175 			}
       
   176 			break;
       
   177 		case RW_INTR_MASK:
       
   178 			D(printf("r_intr_mask=%x\n", value));
       
   179 			s->rw_intr_mask = value;
       
   180 			break;
       
   181 		default:
       
   182 			D(printf ("%s %x %x\n",  __func__, addr, value));
       
   183 			break;
       
   184 	}
       
   185 	ser_update_irq(s);
       
   186 }
       
   187 
       
   188 static CPUReadMemoryFunc *ser_read[] = {
       
   189 	&ser_readb,
       
   190 	&ser_readb,
       
   191 	&ser_readl,
       
   192 };
       
   193 
       
   194 static CPUWriteMemoryFunc *ser_write[] = {
       
   195 	&ser_writeb,
       
   196 	&ser_writeb,
       
   197 	&ser_writel,
       
   198 };
       
   199 
       
   200 static void serial_receive(void *opaque, const uint8_t *buf, int size)
       
   201 {
       
   202 	struct etrax_serial_t *s = opaque;
       
   203 
       
   204 	s->r_intr |= 8;
       
   205 	s->rs_stat_din &= ~0xff;
       
   206 	s->rs_stat_din |= (buf[0] & 0xff);
       
   207 	s->rs_stat_din |= (1 << STAT_DAV); /* dav.  */
       
   208 	ser_update_irq(s);
       
   209 }
       
   210 
       
   211 static int serial_can_receive(void *opaque)
       
   212 {
       
   213 	struct etrax_serial_t *s = opaque;
       
   214 	int r;
       
   215 
       
   216 	/* Is the receiver enabled?  */
       
   217 	r = s->rw_rec_ctrl & 1;
       
   218 
       
   219 	/* Pending rx data?  */
       
   220 	r |= !(s->r_intr & 8);
       
   221 	return r;
       
   222 }
       
   223 
       
   224 static void serial_event(void *opaque, int event)
       
   225 {
       
   226 
       
   227 }
       
   228 
       
   229 void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
       
   230 		      target_phys_addr_t base)
       
   231 {
       
   232 	struct etrax_serial_t *s;
       
   233 	int ser_regs;
       
   234 
       
   235 	s = qemu_mallocz(sizeof *s);
       
   236 	if (!s)
       
   237 		return;
       
   238 
       
   239 	s->env = env;
       
   240 	s->irq = irq;
       
   241 	s->chr = chr;
       
   242 
       
   243 	/* transmitter begins ready and idle.  */
       
   244 	s->rs_stat_din |= (1 << STAT_TR_RDY);
       
   245 	s->rs_stat_din |= (1 << STAT_TR_IDLE);
       
   246 
       
   247 	qemu_chr_add_handlers(chr, serial_can_receive, serial_receive,
       
   248 			      serial_event, s);
       
   249 
       
   250 	ser_regs = cpu_register_io_memory(0, ser_read, ser_write, s);
       
   251 	cpu_register_physical_memory (base, 0x3c, ser_regs);
       
   252 }