Commit 7233b355571ad2a8e7aec7eb19db5f530e81f052

Authored by ths
1 parent d2c38b24

Mainstone re-org, by Armin Kuster.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3758 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -496,9 +496,10 @@ VL_OBJS+= arm-semi.o @@ -496,9 +496,10 @@ VL_OBJS+= arm-semi.o
496 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o 496 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
497 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o 497 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o
498 VL_OBJS+= pflash_cfi01.o gumstix.o 498 VL_OBJS+= pflash_cfi01.o gumstix.o
499 -VL_OBJS+= spitz.o ide.o serial.o nand.o ecc.o mainstone.o 499 +VL_OBJS+= spitz.o ide.o serial.o nand.o ecc.o
500 VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o omap_i2c.o 500 VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o omap_i2c.o
501 VL_OBJS+= palm.o tsc210x.o 501 VL_OBJS+= palm.o tsc210x.o
  502 +VL_OBJS+= mst_fpga.o mainstone.o
502 CPPFLAGS += -DHAS_AUDIO 503 CPPFLAGS += -DHAS_AUDIO
503 endif 504 endif
504 ifeq ($(TARGET_BASE_ARCH), sh4) 505 ifeq ($(TARGET_BASE_ARCH), sh4)
hw/mainstone.c
@@ -14,245 +14,9 @@ @@ -14,245 +14,9 @@
14 #include "net.h" 14 #include "net.h"
15 #include "devices.h" 15 #include "devices.h"
16 #include "boards.h" 16 #include "boards.h"
17 -  
18 -#define MST_ETH_PHYS 0x10000300  
19 -#define MST_FPGA_PHYS 0x08000000  
20 -  
21 -/* Mainstone FPGA for extern irqs */  
22 -#define FPGA_GPIO_PIN 0  
23 -#define MST_NUM_IRQS 16  
24 -#define MST_BASE MST_FPGA_PHYS  
25 -#define MST_LEDDAT1 0x10  
26 -#define MST_LEDDAT2 0x14  
27 -#define MST_LEDCTRL 0x40  
28 -#define MST_GPSWR 0x60  
29 -#define MST_MSCWR1 0x80  
30 -#define MST_MSCWR2 0x84  
31 -#define MST_MSCWR3 0x88  
32 -#define MST_MSCRD 0x90  
33 -#define MST_INTMSKENA 0xc0  
34 -#define MST_INTSETCLR 0xd0  
35 -#define MST_PCMCIA0 0xe0  
36 -#define MST_PCMCIA1 0xe4  
37 -  
38 -/* IRQ definitions */  
39 -#define ETHERNET_IRQ 3  
40 -  
41 -typedef struct mst_irq_state {  
42 - target_phys_addr_t target_base;  
43 - qemu_irq *parent;  
44 - qemu_irq *pins;  
45 -  
46 - uint32_t prev_level;  
47 - uint32_t leddat1;  
48 - uint32_t leddat2;  
49 - uint32_t ledctrl;  
50 - uint32_t gpswr;  
51 - uint32_t mscwr1;  
52 - uint32_t mscwr2;  
53 - uint32_t mscwr3;  
54 - uint32_t mscrd;  
55 - uint32_t intmskena;  
56 - uint32_t intsetclr;  
57 - uint32_t pcmcia0;  
58 - uint32_t pcmcia1;  
59 -} mst_irq_state;  
60 -  
61 -static void  
62 -mst_fpga_update_gpio(mst_irq_state *s)  
63 -{  
64 - uint32_t level, diff;  
65 - int bit;  
66 - level = s->prev_level ^ s->intsetclr;  
67 -  
68 - for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {  
69 - bit = ffs(diff) - 1;  
70 - qemu_set_irq(s->pins[bit], (level >> bit) & 1 );  
71 - }  
72 - s->prev_level = level;  
73 -}  
74 -  
75 -static void  
76 -mst_fpga_set_irq(void *opaque, int irq, int level)  
77 -{  
78 - mst_irq_state *s = (mst_irq_state *)opaque;  
79 -  
80 - if (level)  
81 - s->prev_level |= 1u << irq;  
82 - else  
83 - s->prev_level &= ~(1u << irq);  
84 -  
85 - if(s->intmskena & (1u << irq)) {  
86 - s->intsetclr = 1u << irq;  
87 - qemu_set_irq(s->parent[0], level);  
88 - }  
89 -}  
90 -  
91 -static uint32_t  
92 -mst_fpga_readb(void *opaque, target_phys_addr_t addr)  
93 -{  
94 - mst_irq_state *s = (mst_irq_state *) opaque;  
95 - addr -= s->target_base;  
96 -  
97 - switch (addr) {  
98 - case MST_LEDDAT1:  
99 - return s->leddat1;  
100 - case MST_LEDDAT2:  
101 - return s->leddat2;  
102 - case MST_LEDCTRL:  
103 - return s->ledctrl;  
104 - case MST_GPSWR:  
105 - return s->gpswr;  
106 - case MST_MSCWR1:  
107 - return s->mscwr1;  
108 - case MST_MSCWR2:  
109 - return s->mscwr2;  
110 - case MST_MSCWR3:  
111 - return s->mscwr3;  
112 - case MST_MSCRD:  
113 - return s->mscrd;  
114 - case MST_INTMSKENA:  
115 - return s->intmskena;  
116 - case MST_INTSETCLR:  
117 - return s->intsetclr;  
118 - case MST_PCMCIA0:  
119 - return s->pcmcia0;  
120 - case MST_PCMCIA1:  
121 - return s->pcmcia1;  
122 - default:  
123 - printf("Mainstone - mst_fpga_readb: Bad register offset "  
124 - REG_FMT " \n", addr);  
125 - }  
126 - return 0;  
127 -}  
128 -  
129 -static void  
130 -mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)  
131 -{  
132 - mst_irq_state *s = (mst_irq_state *) opaque;  
133 - addr -= s->target_base;  
134 - value &= 0xffffffff;  
135 -  
136 - switch (addr) {  
137 - case MST_LEDDAT1:  
138 - s->leddat1 = value;  
139 - break;  
140 - case MST_LEDDAT2:  
141 - s->leddat2 = value;  
142 - break;  
143 - case MST_LEDCTRL:  
144 - s->ledctrl = value;  
145 - break;  
146 - case MST_GPSWR:  
147 - s->gpswr = value;  
148 - break;  
149 - case MST_MSCWR1:  
150 - s->mscwr1 = value;  
151 - break;  
152 - case MST_MSCWR2:  
153 - s->mscwr2 = value;  
154 - break;  
155 - case MST_MSCWR3:  
156 - s->mscwr3 = value;  
157 - break;  
158 - case MST_MSCRD:  
159 - s->mscrd = value;  
160 - break;  
161 - case MST_INTMSKENA: /* Mask interupt */  
162 - s->intmskena = (value & 0xFEEFF);  
163 - mst_fpga_update_gpio(s);  
164 - break;  
165 - case MST_INTSETCLR: /* clear or set interrupt */  
166 - s->intsetclr = (value & 0xFEEFF);  
167 - break;  
168 - case MST_PCMCIA0:  
169 - s->pcmcia0 = value;  
170 - break;  
171 - case MST_PCMCIA1:  
172 - s->pcmcia1 = value;  
173 - break;  
174 - default:  
175 - printf("Mainstone - mst_fpga_writeb: Bad register offset "  
176 - REG_FMT " \n", addr);  
177 - }  
178 -}  
179 -  
180 -CPUReadMemoryFunc *mst_fpga_readfn[] = {  
181 - mst_fpga_readb,  
182 - mst_fpga_readb,  
183 - mst_fpga_readb,  
184 -};  
185 -CPUWriteMemoryFunc *mst_fpga_writefn[] = {  
186 - mst_fpga_writeb,  
187 - mst_fpga_writeb,  
188 - mst_fpga_writeb,  
189 -};  
190 -  
191 -static void  
192 -mst_fpga_save(QEMUFile *f, void *opaque)  
193 -{  
194 - struct mst_irq_state *s = (mst_irq_state *) opaque;  
195 -  
196 - qemu_put_be32s(f, &s->prev_level);  
197 - qemu_put_be32s(f, &s->leddat1);  
198 - qemu_put_be32s(f, &s->leddat2);  
199 - qemu_put_be32s(f, &s->ledctrl);  
200 - qemu_put_be32s(f, &s->gpswr);  
201 - qemu_put_be32s(f, &s->mscwr1);  
202 - qemu_put_be32s(f, &s->mscwr2);  
203 - qemu_put_be32s(f, &s->mscwr3);  
204 - qemu_put_be32s(f, &s->mscrd);  
205 - qemu_put_be32s(f, &s->intmskena);  
206 - qemu_put_be32s(f, &s->intsetclr);  
207 - qemu_put_be32s(f, &s->pcmcia0);  
208 - qemu_put_be32s(f, &s->pcmcia1);  
209 -}  
210 -  
211 -static int  
212 -mst_fpga_load(QEMUFile *f, void *opaque, int version_id)  
213 -{  
214 - mst_irq_state *s = (mst_irq_state *) opaque;  
215 -  
216 - qemu_get_be32s(f, &s->prev_level);  
217 - qemu_get_be32s(f, &s->leddat1);  
218 - qemu_get_be32s(f, &s->leddat2);  
219 - qemu_get_be32s(f, &s->ledctrl);  
220 - qemu_get_be32s(f, &s->gpswr);  
221 - qemu_get_be32s(f, &s->mscwr1);  
222 - qemu_get_be32s(f, &s->mscwr2);  
223 - qemu_get_be32s(f, &s->mscwr3);  
224 - qemu_get_be32s(f, &s->mscrd);  
225 - qemu_get_be32s(f, &s->intmskena);  
226 - qemu_get_be32s(f, &s->intsetclr);  
227 - qemu_get_be32s(f, &s->pcmcia0);  
228 - qemu_get_be32s(f, &s->pcmcia1);  
229 - return 0;  
230 -}  
231 -  
232 -static qemu_irq  
233 -*mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq)  
234 -{  
235 - mst_irq_state *s;  
236 - int iomemtype;  
237 - qemu_irq *qi;  
238 -  
239 - s = (mst_irq_state *) qemu_mallocz(sizeof(mst_irq_state));  
240 -  
241 - if (!s)  
242 - return NULL;  
243 - s->target_base = base;  
244 - s->parent = &cpu->pic[irq];  
245 -  
246 - /* alloc the external 16 irqs */  
247 - qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);  
248 - s->pins = qi;  
249 -  
250 - iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,  
251 - mst_fpga_writefn, s);  
252 - cpu_register_physical_memory(MST_BASE, 0x00100000, iomemtype);  
253 - register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);  
254 - return qi;  
255 -} 17 +#include "mainstone.h"
  18 +#include "sysemu.h"
  19 +#include "flash.h"
256 20
257 enum mainstone_model_e { mainstone }; 21 enum mainstone_model_e { mainstone };
258 22
@@ -283,7 +47,20 @@ static void mainstone_common_init(int ram_size, int vga_ram_size, @@ -283,7 +47,20 @@ static void mainstone_common_init(int ram_size, int vga_ram_size,
283 /* Setup initial (reset) machine state */ 47 /* Setup initial (reset) machine state */
284 cpu->env->regs[15] = PXA2XX_SDRAM_BASE; 48 cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
285 49
286 - mst_irq = mst_irq_init(cpu, MST_BASE, PXA2XX_PIC_GPIO_0); 50 + /* There are two 32MiB flash devices on the board */
  51 + if (!pflash_register(MST_FLASH_0, mainstone_ram + PXA2XX_INTERNAL_SIZE,
  52 + pflash_table[0], 256 * 1024, 128, 4, 0, 0, 0, 0)) {
  53 + fprintf(stderr, "qemu: Error register flash memory.\n");
  54 + exit(1);
  55 + }
  56 +
  57 + if (!pflash_register(MST_FLASH_1, mainstone_ram + PXA2XX_INTERNAL_SIZE,
  58 + pflash_table[1], 256 * 1024, 128, 4, 0, 0, 0, 0)) {
  59 + fprintf(stderr, "qemu: Error register flash memory.\n");
  60 + exit(1);
  61 + }
  62 +
  63 + mst_irq = mst_irq_init(cpu, MST_FPGA_PHYS, PXA2XX_PIC_GPIO_0);
287 smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]); 64 smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
288 65
289 arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline, 66 arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline,
hw/mainstone.h 0 โ†’ 100644
  1 +/*
  2 + * PXA270-based Intel Mainstone platforms.
  3 + *
  4 + * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
  5 + * <akuster@mvista.com>
  6 + *
  7 + * This code is licensed under the GNU GPL v2.
  8 + */
  9 +
  10 +#ifndef __MAINSTONE_H__
  11 +#define __MAINSTONE_H__
  12 +
  13 +/* Device addresses */
  14 +#define MST_FPGA_PHYS 0x08000000
  15 +#define MST_ETH_PHYS 0x10000300
  16 +#define MST_FLASH_0 0x00000000
  17 +#define MST_FLASH_1 0x04000000
  18 +
  19 +/* IRQ definitions */
  20 +#define ETHERNET_IRQ 3
  21 +
  22 +extern qemu_irq
  23 +*mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq);
  24 +
  25 +#endif /* __MAINSTONE_H__ */
hw/mst_fpga.c 0 โ†’ 100644
  1 +/*
  2 + * PXA270-based Intel Mainstone platforms.
  3 + * FPGA driver
  4 + *
  5 + * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
  6 + * <akuster@mvista.com>
  7 + *
  8 + * This code is licensed under the GNU GPL v2.
  9 + */
  10 +#include "hw.h"
  11 +#include "pxa.h"
  12 +#include "mainstone.h"
  13 +
  14 +/* Mainstone FPGA for extern irqs */
  15 +#define FPGA_GPIO_PIN 0
  16 +#define MST_NUM_IRQS 16
  17 +#define MST_BASE MST_FPGA_PHYS
  18 +#define MST_LEDDAT1 0x10
  19 +#define MST_LEDDAT2 0x14
  20 +#define MST_LEDCTRL 0x40
  21 +#define MST_GPSWR 0x60
  22 +#define MST_MSCWR1 0x80
  23 +#define MST_MSCWR2 0x84
  24 +#define MST_MSCWR3 0x88
  25 +#define MST_MSCRD 0x90
  26 +#define MST_INTMSKENA 0xc0
  27 +#define MST_INTSETCLR 0xd0
  28 +#define MST_PCMCIA0 0xe0
  29 +#define MST_PCMCIA1 0xe4
  30 +
  31 +typedef struct mst_irq_state{
  32 + target_phys_addr_t target_base;
  33 + qemu_irq *parent;
  34 + qemu_irq *pins;
  35 +
  36 + uint32_t prev_level;
  37 + uint32_t leddat1;
  38 + uint32_t leddat2;
  39 + uint32_t ledctrl;
  40 + uint32_t gpswr;
  41 + uint32_t mscwr1;
  42 + uint32_t mscwr2;
  43 + uint32_t mscwr3;
  44 + uint32_t mscrd;
  45 + uint32_t intmskena;
  46 + uint32_t intsetclr;
  47 + uint32_t pcmcia0;
  48 + uint32_t pcmcia1;
  49 +}mst_irq_state;
  50 +
  51 +static void
  52 +mst_fpga_update_gpio(mst_irq_state *s)
  53 +{
  54 + uint32_t level, diff;
  55 + int bit;
  56 + level = s->prev_level ^ s->intsetclr;
  57 +
  58 + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
  59 + bit = ffs(diff) - 1;
  60 + qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
  61 + }
  62 + s->prev_level = level;
  63 +}
  64 +
  65 +static void
  66 +mst_fpga_set_irq(void *opaque, int irq, int level)
  67 +{
  68 + mst_irq_state *s = (mst_irq_state *)opaque;
  69 +
  70 + if (level)
  71 + s->prev_level |= 1u << irq;
  72 + else
  73 + s->prev_level &= ~(1u << irq);
  74 +
  75 + if(s->intmskena & (1u << irq)) {
  76 + s->intsetclr = 1u << irq;
  77 + qemu_set_irq(s->parent[0], level);
  78 + }
  79 +}
  80 +
  81 +
  82 +static uint32_t
  83 +mst_fpga_readb(void *opaque, target_phys_addr_t addr)
  84 +{
  85 + mst_irq_state *s = (mst_irq_state *) opaque;
  86 + addr -= s->target_base;
  87 +
  88 + switch (addr) {
  89 + case MST_LEDDAT1:
  90 + return s->leddat1;
  91 + case MST_LEDDAT2:
  92 + return s->leddat2;
  93 + case MST_LEDCTRL:
  94 + return s->ledctrl;
  95 + case MST_GPSWR:
  96 + return s->gpswr;
  97 + case MST_MSCWR1:
  98 + return s->mscwr1;
  99 + case MST_MSCWR2:
  100 + return s->mscwr2;
  101 + case MST_MSCWR3:
  102 + return s->mscwr3;
  103 + case MST_MSCRD:
  104 + return s->mscrd;
  105 + case MST_INTMSKENA:
  106 + return s->intmskena;
  107 + case MST_INTSETCLR:
  108 + return s->intsetclr;
  109 + case MST_PCMCIA0:
  110 + return s->pcmcia0;
  111 + case MST_PCMCIA1:
  112 + return s->pcmcia1;
  113 + default:
  114 + printf("Mainstone - mst_fpga_readb: Bad register offset "
  115 + REG_FMT " \n", addr);
  116 + }
  117 + return 0;
  118 +}
  119 +
  120 +static void
  121 +mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
  122 +{
  123 + mst_irq_state *s = (mst_irq_state *) opaque;
  124 + addr -= s->target_base;
  125 + value &= 0xffffffff;
  126 +
  127 + switch (addr) {
  128 + case MST_LEDDAT1:
  129 + s->leddat1 = value;
  130 + break;
  131 + case MST_LEDDAT2:
  132 + s->leddat2 = value;
  133 + break;
  134 + case MST_LEDCTRL:
  135 + s->ledctrl = value;
  136 + break;
  137 + case MST_GPSWR:
  138 + s->gpswr = value;
  139 + break;
  140 + case MST_MSCWR1:
  141 + s->mscwr1 = value;
  142 + break;
  143 + case MST_MSCWR2:
  144 + s->mscwr2 = value;
  145 + break;
  146 + case MST_MSCWR3:
  147 + s->mscwr3 = value;
  148 + break;
  149 + case MST_MSCRD:
  150 + s->mscrd = value;
  151 + break;
  152 + case MST_INTMSKENA: /* Mask interupt */
  153 + s->intmskena = (value & 0xFEEFF);
  154 + mst_fpga_update_gpio(s);
  155 + break;
  156 + case MST_INTSETCLR: /* clear or set interrupt */
  157 + s->intsetclr = (value & 0xFEEFF);
  158 + break;
  159 + case MST_PCMCIA0:
  160 + s->pcmcia0 = value;
  161 + break;
  162 + case MST_PCMCIA1:
  163 + s->pcmcia1 = value;
  164 + break;
  165 + default:
  166 + printf("Mainstone - mst_fpga_writeb: Bad register offset "
  167 + REG_FMT " \n", addr);
  168 + }
  169 +}
  170 +
  171 +CPUReadMemoryFunc *mst_fpga_readfn[] = {
  172 + mst_fpga_readb,
  173 + mst_fpga_readb,
  174 + mst_fpga_readb,
  175 +};
  176 +CPUWriteMemoryFunc *mst_fpga_writefn[] = {
  177 + mst_fpga_writeb,
  178 + mst_fpga_writeb,
  179 + mst_fpga_writeb,
  180 +};
  181 +
  182 +static void
  183 +mst_fpga_save(QEMUFile *f, void *opaque)
  184 +{
  185 + struct mst_irq_state *s = (mst_irq_state *) opaque;
  186 +
  187 + qemu_put_be32s(f, &s->prev_level);
  188 + qemu_put_be32s(f, &s->leddat1);
  189 + qemu_put_be32s(f, &s->leddat2);
  190 + qemu_put_be32s(f, &s->ledctrl);
  191 + qemu_put_be32s(f, &s->gpswr);
  192 + qemu_put_be32s(f, &s->mscwr1);
  193 + qemu_put_be32s(f, &s->mscwr2);
  194 + qemu_put_be32s(f, &s->mscwr3);
  195 + qemu_put_be32s(f, &s->mscrd);
  196 + qemu_put_be32s(f, &s->intmskena);
  197 + qemu_put_be32s(f, &s->intsetclr);
  198 + qemu_put_be32s(f, &s->pcmcia0);
  199 + qemu_put_be32s(f, &s->pcmcia1);
  200 +}
  201 +
  202 +static int
  203 +mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
  204 +{
  205 + mst_irq_state *s = (mst_irq_state *) opaque;
  206 +
  207 + qemu_get_be32s(f, &s->prev_level);
  208 + qemu_get_be32s(f, &s->leddat1);
  209 + qemu_get_be32s(f, &s->leddat2);
  210 + qemu_get_be32s(f, &s->ledctrl);
  211 + qemu_get_be32s(f, &s->gpswr);
  212 + qemu_get_be32s(f, &s->mscwr1);
  213 + qemu_get_be32s(f, &s->mscwr2);
  214 + qemu_get_be32s(f, &s->mscwr3);
  215 + qemu_get_be32s(f, &s->mscrd);
  216 + qemu_get_be32s(f, &s->intmskena);
  217 + qemu_get_be32s(f, &s->intsetclr);
  218 + qemu_get_be32s(f, &s->pcmcia0);
  219 + qemu_get_be32s(f, &s->pcmcia1);
  220 + return 0;
  221 +}
  222 +
  223 +qemu_irq *mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq)
  224 +{
  225 + mst_irq_state *s;
  226 + int iomemtype;
  227 + qemu_irq *qi;
  228 +
  229 + s = (mst_irq_state *)
  230 + qemu_mallocz(sizeof(mst_irq_state));
  231 +
  232 + if (!s)
  233 + return NULL;
  234 + s->target_base = base;
  235 + s->parent = &cpu->pic[irq];
  236 +
  237 + /* alloc the external 16 irqs */
  238 + qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
  239 + s->pins = qi;
  240 +
  241 + iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,
  242 + mst_fpga_writefn, s);
  243 + cpu_register_physical_memory(MST_BASE, 0x00100000, iomemtype);
  244 + register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
  245 + return qi;
  246 +}