Commit f062058fa174611d4c1bbc28e40b14be4bce89f8

Authored by edgar_igl
1 parent b41f7df0

ETRAX serial port:

* Simulate basic interrupt driven serial io.
* Connect to qemu char dev.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4300 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 164 additions and 29 deletions
hw/etraxfs_ser.c
... ... @@ -25,21 +25,68 @@
25 25 #include <stdio.h>
26 26 #include <ctype.h>
27 27 #include "hw.h"
  28 +#include "qemu-char.h"
28 29  
29 30 #define D(x)
30 31  
31   -#define RW_TR_DMA_EN 0x04
32   -#define RW_DOUT 0x1c
33   -#define RW_STAT_DIN 0x20
34   -#define R_STAT_DIN 0x24
  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
35 42  
36   -static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
  43 +#define STAT_DAV 16
  44 +#define STAT_TR_IDLE 22
  45 +#define STAT_TR_RDY 24
  46 +
  47 +struct etrax_serial_t
37 48 {
38   - D(CPUState *env = opaque);
39   - D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
40   - return 0;
  49 + CPUState *env;
  50 + CharDriverState *chr;
  51 + qemu_irq *irq;
  52 +
  53 + target_phys_addr_t base;
  54 +
  55 + int pending_tx;
  56 +
  57 + /* Control registers. */
  58 + uint32_t rw_tr_ctrl;
  59 + uint32_t rw_tr_dma_en;
  60 + uint32_t rw_rec_ctrl;
  61 + uint32_t rs_stat_din;
  62 + uint32_t r_stat_din;
  63 + uint32_t rw_intr_mask;
  64 + uint32_t rw_ack_intr;
  65 + uint32_t r_intr;
  66 + uint32_t r_masked_intr;
  67 +};
  68 +
  69 +static void ser_update_irq(struct etrax_serial_t *s)
  70 +{
  71 + uint32_t o_irq = s->r_masked_intr;
  72 +
  73 + s->r_intr &= ~(s->rw_ack_intr);
  74 + s->r_masked_intr = s->r_intr & s->rw_intr_mask;
  75 +
  76 + if (o_irq != s->r_masked_intr) {
  77 + D(printf("irq_mask=%x r_intr=%x rmi=%x airq=%x \n",
  78 + s->rw_intr_mask, s->r_intr,
  79 + s->r_masked_intr, s->rw_ack_intr));
  80 + if (s->r_masked_intr)
  81 + qemu_irq_raise(s->irq[0]);
  82 + else
  83 + qemu_irq_lower(s->irq[0]);
  84 + }
  85 + s->rw_ack_intr = 0;
41 86 }
42   -static uint32_t ser_readw (void *opaque, target_phys_addr_t addr)
  87 +
  88 +
  89 +static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
43 90 {
44 91 D(CPUState *env = opaque);
45 92 D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
... ... @@ -48,16 +95,40 @@ static uint32_t ser_readw (void *opaque, target_phys_addr_t addr)
48 95  
49 96 static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
50 97 {
51   - D(CPUState *env = opaque);
  98 + struct etrax_serial_t *s = opaque;
  99 + D(CPUState *env = s->env);
52 100 uint32_t r = 0;
53 101  
54 102 switch (addr & 0xfff)
55 103 {
  104 + case RW_TR_CTRL:
  105 + r = s->rw_tr_ctrl;
  106 + break;
56 107 case RW_TR_DMA_EN:
  108 + r = s->rw_tr_dma_en;
  109 + break;
  110 + case RS_STAT_DIN:
  111 + r = s->rs_stat_din;
  112 + /* clear dav. */
  113 + s->rs_stat_din &= ~(1 << STAT_DAV);
57 114 break;
58 115 case R_STAT_DIN:
59   - r |= 1 << 24; /* set tr_rdy. */
60   - r |= 1 << 22; /* set tr_idle. */
  116 + r = s->rs_stat_din;
  117 + break;
  118 + case RW_ACK_INTR:
  119 + D(printf("load rw_ack_intr=%x\n", s->rw_ack_intr));
  120 + r = s->rw_ack_intr;
  121 + break;
  122 + case RW_INTR_MASK:
  123 + r = s->rw_intr_mask;
  124 + break;
  125 + case R_INTR:
  126 + D(printf("load r_intr=%x\n", s->r_intr));
  127 + r = s->r_intr;
  128 + break;
  129 + case R_MASKED_INTR:
  130 + D(printf("load r_maked_intr=%x\n", s->r_masked_intr));
  131 + r = s->r_masked_intr;
61 132 break;
62 133  
63 134 default:
... ... @@ -70,53 +141,117 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
70 141 static void
71 142 ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
72 143 {
73   - D(CPUState *env = opaque);
  144 + D(struct etrax_serial_t *s = opaque);
  145 + D(CPUState *env = s->env);
74 146 D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
75 147 }
76 148 static void
77   -ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
78   -{
79   - D(CPUState *env = opaque);
80   - D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
81   -}
82   -static void
83 149 ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
84 150 {
85   - D(CPUState *env = opaque);
  151 + struct etrax_serial_t *s = opaque;
  152 + unsigned char ch = value;
  153 + D(CPUState *env = s->env);
86 154  
87 155 switch (addr & 0xfff)
88 156 {
  157 + case RW_TR_CTRL:
  158 + D(printf("rw_tr_ctrl=%x\n", value));
  159 + s->rw_tr_ctrl = value;
  160 + break;
89 161 case RW_TR_DMA_EN:
  162 + D(printf("rw_tr_dma_en=%x\n", value));
  163 + s->rw_tr_dma_en = value;
90 164 break;
91 165 case RW_DOUT:
92   - if (isprint(value) || isspace(value))
93   - putchar(value);
94   - else
95   - putchar('.');
96   - fflush(stdout);
  166 + qemu_chr_write(s->chr, &ch, 1);
  167 + s->r_intr |= 1;
  168 + s->pending_tx = 1;
  169 + break;
  170 + case RW_ACK_INTR:
  171 + D(printf("rw_ack_intr=%x\n", value));
  172 + s->rw_ack_intr = value;
  173 + if (s->pending_tx && (s->rw_ack_intr & 1)) {
  174 + s->r_intr |= 1;
  175 + s->pending_tx = 0;
  176 + s->rw_ack_intr &= ~1;
  177 + }
  178 + break;
  179 + case RW_INTR_MASK:
  180 + D(printf("r_intr_mask=%x\n", value));
  181 + s->rw_intr_mask = value;
97 182 break;
98 183 default:
99 184 D(printf ("%s %x %x pc=%x\n",
100 185 __func__, addr, value, env->pc));
101 186 break;
102 187 }
  188 + ser_update_irq(s);
103 189 }
104 190  
105 191 static CPUReadMemoryFunc *ser_read[] = {
106 192 &ser_readb,
107   - &ser_readw,
  193 + &ser_readb,
108 194 &ser_readl,
109 195 };
110 196  
111 197 static CPUWriteMemoryFunc *ser_write[] = {
112 198 &ser_writeb,
113   - &ser_writew,
  199 + &ser_writeb,
114 200 &ser_writel,
115 201 };
116 202  
117   -void etraxfs_ser_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base)
  203 +static void serial_receive(void *opaque, const uint8_t *buf, int size)
118 204 {
  205 + struct etrax_serial_t *s = opaque;
  206 +
  207 + s->r_intr |= 8;
  208 + s->rs_stat_din &= ~0xff;
  209 + s->rs_stat_din |= (buf[0] & 0xff);
  210 + s->rs_stat_din |= (1 << STAT_DAV); /* dav. */
  211 + ser_update_irq(s);
  212 +}
  213 +
  214 +static int serial_can_receive(void *opaque)
  215 +{
  216 + struct etrax_serial_t *s = opaque;
  217 + int r;
  218 +
  219 + /* Is the receiver enabled? */
  220 + r = s->rw_rec_ctrl & 1;
  221 +
  222 + /* Pending rx data? */
  223 + r |= !(s->r_intr & 8);
  224 + return r;
  225 +}
  226 +
  227 +static void serial_event(void *opaque, int event)
  228 +{
  229 +
  230 +}
  231 +
  232 +void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
  233 + target_phys_addr_t base)
  234 +{
  235 + struct etrax_serial_t *s;
119 236 int ser_regs;
120   - ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env);
  237 +
  238 + s = qemu_mallocz(sizeof *s);
  239 + if (!s)
  240 + return;
  241 +
  242 + s->env = env;
  243 + s->irq = irq;
  244 + s->base = base;
  245 +
  246 + s->chr = chr;
  247 +
  248 + /* transmitter begins ready and idle. */
  249 + s->rs_stat_din |= (1 << STAT_TR_RDY);
  250 + s->rs_stat_din |= (1 << STAT_TR_IDLE);
  251 +
  252 + qemu_chr_add_handlers(chr, serial_can_receive, serial_receive,
  253 + serial_event, s);
  254 +
  255 + ser_regs = cpu_register_io_memory(0, ser_read, ser_write, s);
121 256 cpu_register_physical_memory (base, 0x3c, ser_regs);
122 257 }
... ...