Commit a171fe394a82e3a2dad76e901959d859b1966541

Authored by balrog
1 parent 2bac6019

Add remaining PXA2xx on-chip peripherals except I2C master.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2751 c046a42c-6fe2-441c-8c8c-71466251a162
hw/pxa.h
... ... @@ -63,6 +63,12 @@
63 63 struct pxa2xx_pic_state_s;
64 64 qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
65 65  
  66 +/* pxa2xx_timer.c */
  67 +void pxa25x_timer_init(target_phys_addr_t base,
  68 + qemu_irq *irqs, CPUState *cpustate);
  69 +void pxa27x_timer_init(target_phys_addr_t base,
  70 + qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate);
  71 +
66 72 /* pxa2xx_gpio.c */
67 73 struct pxa2xx_gpio_info_s;
68 74 struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
... ... @@ -81,6 +87,29 @@ struct pxa2xx_dma_state_s *pxa27x_dma_init(target_phys_addr_t base,
81 87 qemu_irq irq);
82 88 void pxa2xx_dma_request(struct pxa2xx_dma_state_s *s, int req_num, int on);
83 89  
  90 +/* pxa2xx_lcd.c */
  91 +struct pxa2xx_lcdc_s;
  92 +struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base,
  93 + qemu_irq irq, DisplayState *ds);
  94 +void pxa2xx_lcd_vsync_cb(struct pxa2xx_lcdc_s *s,
  95 + void (*cb)(void *opaque), void *opaque);
  96 +void pxa2xx_lcdc_oritentation(void *opaque, int angle);
  97 +
  98 +/* pxa2xx_mmci.c */
  99 +struct pxa2xx_mmci_s;
  100 +struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
  101 + qemu_irq irq, void *dma);
  102 +void pxa2xx_mmci_handlers(struct pxa2xx_mmci_s *s, void *opaque,
  103 + void (*readonly_cb)(void *, int),
  104 + void (*coverswitch_cb)(void *, int));
  105 +
  106 +/* pxa2xx_pcmcia.c */
  107 +struct pxa2xx_pcmcia_s;
  108 +struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base);
  109 +int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card);
  110 +int pxa2xx_pcmcia_dettach(void *opaque);
  111 +void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
  112 +
84 113 /* pxa2xx.c */
85 114 struct pxa2xx_ssp_s;
86 115 void pxa2xx_ssp_attach(struct pxa2xx_ssp_s *port,
... ... @@ -95,7 +124,10 @@ struct pxa2xx_state_s {
95 124 qemu_irq *pic;
96 125 struct pxa2xx_dma_state_s *dma;
97 126 struct pxa2xx_gpio_info_s *gpio;
  127 + struct pxa2xx_lcdc_s *lcd;
98 128 struct pxa2xx_ssp_s **ssp;
  129 + struct pxa2xx_mmci_s *mmc;
  130 + struct pxa2xx_pcmcia_s *pcmcia[2];
99 131 struct pxa2xx_i2s_s *i2s;
100 132 struct pxa2xx_fir_s *fir;
101 133  
... ...
hw/pxa2xx.c
... ... @@ -1531,8 +1531,13 @@ struct pxa2xx_state_s *pxa270_init(DisplayState *ds, const char *revision)
1531 1531  
1532 1532 s->dma = pxa27x_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
1533 1533  
  1534 + pxa27x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0],
  1535 + s->pic[PXA27X_PIC_OST_4_11], s->env);
  1536 +
1534 1537 s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
1535 1538  
  1539 + s->mmc = pxa2xx_mmci_init(0x41100000, s->pic[PXA2XX_PIC_MMC], s->dma);
  1540 +
1536 1541 for (i = 0; pxa270_serial[i].io_base; i ++)
1537 1542 if (serial_hds[i])
1538 1543 serial_mm_init(pxa270_serial[i].io_base, 2,
... ... @@ -1543,6 +1548,9 @@ struct pxa2xx_state_s *pxa270_init(DisplayState *ds, const char *revision)
1543 1548 s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
1544 1549 s->dma, serial_hds[i]);
1545 1550  
  1551 + if (ds)
  1552 + s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD], ds);
  1553 +
1546 1554 s->cm_base = 0x41300000;
1547 1555 s->cm_regs[CCCR >> 4] = 0x02000210; /* 416.0 MHz */
1548 1556 s->clkcfg = 0x00000009; /* Turbo mode active */
... ... @@ -1575,6 +1583,13 @@ struct pxa2xx_state_s *pxa270_init(DisplayState *ds, const char *revision)
1575 1583 cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
1576 1584 }
1577 1585  
  1586 + if (usb_enabled) {
  1587 + usb_ohci_init_pxa(0x4c000000, 3, -1, s->pic[PXA2XX_PIC_USBH1]);
  1588 + }
  1589 +
  1590 + s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
  1591 + s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
  1592 +
1578 1593 s->rtc_base = 0x40900000;
1579 1594 iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
1580 1595 pxa2xx_rtc_writefn, s);
... ... @@ -1609,8 +1624,12 @@ struct pxa2xx_state_s *pxa255_init(DisplayState *ds)
1609 1624  
1610 1625 s->dma = pxa255_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
1611 1626  
  1627 + pxa25x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0], s->env);
  1628 +
1612 1629 s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
1613 1630  
  1631 + s->mmc = pxa2xx_mmci_init(0x41100000, s->pic[PXA2XX_PIC_MMC], s->dma);
  1632 +
1614 1633 for (i = 0; pxa255_serial[i].io_base; i ++)
1615 1634 if (serial_hds[i])
1616 1635 serial_mm_init(pxa255_serial[i].io_base, 2,
... ... @@ -1621,6 +1640,9 @@ struct pxa2xx_state_s *pxa255_init(DisplayState *ds)
1621 1640 s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
1622 1641 s->dma, serial_hds[i]);
1623 1642  
  1643 + if (ds)
  1644 + s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD], ds);
  1645 +
1624 1646 s->cm_base = 0x41300000;
1625 1647 s->cm_regs[CCCR >> 4] = 0x02000210; /* 416.0 MHz */
1626 1648 s->clkcfg = 0x00000009; /* Turbo mode active */
... ... @@ -1653,6 +1675,13 @@ struct pxa2xx_state_s *pxa255_init(DisplayState *ds)
1653 1675 cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
1654 1676 }
1655 1677  
  1678 + if (usb_enabled) {
  1679 + usb_ohci_init_pxa(0x4c000000, 3, -1, s->pic[PXA2XX_PIC_USBH1]);
  1680 + }
  1681 +
  1682 + s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
  1683 + s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
  1684 +
1656 1685 s->rtc_base = 0x40900000;
1657 1686 iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
1658 1687 pxa2xx_rtc_writefn, s);
... ...
hw/pxa2xx_lcd.c 0 โ†’ 100644
  1 +/*
  2 + * Intel XScale PXA255/270 LCDC emulation.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  6 + *
  7 + * This code is licensed under the GPLv2.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int, int);
  13 +
  14 +struct pxa2xx_lcdc_s {
  15 + target_phys_addr_t base;
  16 + qemu_irq irq;
  17 + int irqlevel;
  18 +
  19 + int invalidated;
  20 + DisplayState *ds;
  21 + drawfn *line_fn[2];
  22 + int dest_width;
  23 + int xres, yres;
  24 + int pal_for;
  25 + int transp;
  26 + enum {
  27 + pxa_lcdc_2bpp = 1,
  28 + pxa_lcdc_4bpp = 2,
  29 + pxa_lcdc_8bpp = 3,
  30 + pxa_lcdc_16bpp = 4,
  31 + pxa_lcdc_18bpp = 5,
  32 + pxa_lcdc_18pbpp = 6,
  33 + pxa_lcdc_19bpp = 7,
  34 + pxa_lcdc_19pbpp = 8,
  35 + pxa_lcdc_24bpp = 9,
  36 + pxa_lcdc_25bpp = 10,
  37 + } bpp;
  38 +
  39 + uint32_t control[6];
  40 + uint32_t status[2];
  41 + uint32_t ovl1c[2];
  42 + uint32_t ovl2c[2];
  43 + uint32_t ccr;
  44 + uint32_t cmdcr;
  45 + uint32_t trgbr;
  46 + uint32_t tcr;
  47 + uint32_t liidr;
  48 + uint8_t bscntr;
  49 +
  50 + struct {
  51 + target_phys_addr_t branch;
  52 + int up;
  53 + uint8_t palette[1024];
  54 + uint8_t pbuffer[1024];
  55 + void (*redraw)(struct pxa2xx_lcdc_s *s, uint8_t *fb,
  56 + int *miny, int *maxy);
  57 +
  58 + target_phys_addr_t descriptor;
  59 + target_phys_addr_t source;
  60 + uint32_t id;
  61 + uint32_t command;
  62 + } dma_ch[7];
  63 +
  64 + void (*vsync_cb)(void *opaque);
  65 + void *opaque;
  66 + int orientation;
  67 +};
  68 +
  69 +struct __attribute__ ((__packed__)) pxa_frame_descriptor_s {
  70 + uint32_t fdaddr;
  71 + uint32_t fsaddr;
  72 + uint32_t fidr;
  73 + uint32_t ldcmd;
  74 +};
  75 +
  76 +#define LCCR0 0x000 /* LCD Controller Control register 0 */
  77 +#define LCCR1 0x004 /* LCD Controller Control register 1 */
  78 +#define LCCR2 0x008 /* LCD Controller Control register 2 */
  79 +#define LCCR3 0x00c /* LCD Controller Control register 3 */
  80 +#define LCCR4 0x010 /* LCD Controller Control register 4 */
  81 +#define LCCR5 0x014 /* LCD Controller Control register 5 */
  82 +
  83 +#define FBR0 0x020 /* DMA Channel 0 Frame Branch register */
  84 +#define FBR1 0x024 /* DMA Channel 1 Frame Branch register */
  85 +#define FBR2 0x028 /* DMA Channel 2 Frame Branch register */
  86 +#define FBR3 0x02c /* DMA Channel 3 Frame Branch register */
  87 +#define FBR4 0x030 /* DMA Channel 4 Frame Branch register */
  88 +#define FBR5 0x110 /* DMA Channel 5 Frame Branch register */
  89 +#define FBR6 0x114 /* DMA Channel 6 Frame Branch register */
  90 +
  91 +#define LCSR1 0x034 /* LCD Controller Status register 1 */
  92 +#define LCSR0 0x038 /* LCD Controller Status register 0 */
  93 +#define LIIDR 0x03c /* LCD Controller Interrupt ID register */
  94 +
  95 +#define TRGBR 0x040 /* TMED RGB Seed register */
  96 +#define TCR 0x044 /* TMED Control register */
  97 +
  98 +#define OVL1C1 0x050 /* Overlay 1 Control register 1 */
  99 +#define OVL1C2 0x060 /* Overlay 1 Control register 2 */
  100 +#define OVL2C1 0x070 /* Overlay 2 Control register 1 */
  101 +#define OVL2C2 0x080 /* Overlay 2 Control register 2 */
  102 +#define CCR 0x090 /* Cursor Control register */
  103 +
  104 +#define CMDCR 0x100 /* Command Control register */
  105 +#define PRSR 0x104 /* Panel Read Status register */
  106 +
  107 +#define PXA_LCDDMA_CHANS 7
  108 +#define DMA_FDADR 0x00 /* Frame Descriptor Address register */
  109 +#define DMA_FSADR 0x04 /* Frame Source Address register */
  110 +#define DMA_FIDR 0x08 /* Frame ID register */
  111 +#define DMA_LDCMD 0x0c /* Command register */
  112 +
  113 +/* LCD Buffer Strength Control register */
  114 +#define BSCNTR 0x04000054
  115 +
  116 +/* Bitfield masks */
  117 +#define LCCR0_ENB (1 << 0)
  118 +#define LCCR0_CMS (1 << 1)
  119 +#define LCCR0_SDS (1 << 2)
  120 +#define LCCR0_LDM (1 << 3)
  121 +#define LCCR0_SOFM0 (1 << 4)
  122 +#define LCCR0_IUM (1 << 5)
  123 +#define LCCR0_EOFM0 (1 << 6)
  124 +#define LCCR0_PAS (1 << 7)
  125 +#define LCCR0_DPD (1 << 9)
  126 +#define LCCR0_DIS (1 << 10)
  127 +#define LCCR0_QDM (1 << 11)
  128 +#define LCCR0_PDD (0xff << 12)
  129 +#define LCCR0_BSM0 (1 << 20)
  130 +#define LCCR0_OUM (1 << 21)
  131 +#define LCCR0_LCDT (1 << 22)
  132 +#define LCCR0_RDSTM (1 << 23)
  133 +#define LCCR0_CMDIM (1 << 24)
  134 +#define LCCR0_OUC (1 << 25)
  135 +#define LCCR0_LDDALT (1 << 26)
  136 +#define LCCR1_PPL(x) ((x) & 0x3ff)
  137 +#define LCCR2_LPP(x) ((x) & 0x3ff)
  138 +#define LCCR3_API (15 << 16)
  139 +#define LCCR3_BPP(x) ((((x) >> 24) & 7) | (((x) >> 26) & 8))
  140 +#define LCCR3_PDFOR(x) (((x) >> 30) & 3)
  141 +#define LCCR4_K1(x) (((x) >> 0) & 7)
  142 +#define LCCR4_K2(x) (((x) >> 3) & 7)
  143 +#define LCCR4_K3(x) (((x) >> 6) & 7)
  144 +#define LCCR4_PALFOR(x) (((x) >> 15) & 3)
  145 +#define LCCR5_SOFM(ch) (1 << (ch - 1))
  146 +#define LCCR5_EOFM(ch) (1 << (ch + 7))
  147 +#define LCCR5_BSM(ch) (1 << (ch + 15))
  148 +#define LCCR5_IUM(ch) (1 << (ch + 23))
  149 +#define OVLC1_EN (1 << 31)
  150 +#define CCR_CEN (1 << 31)
  151 +#define FBR_BRA (1 << 0)
  152 +#define FBR_BINT (1 << 1)
  153 +#define FBR_SRCADDR (0xfffffff << 4)
  154 +#define LCSR0_LDD (1 << 0)
  155 +#define LCSR0_SOF0 (1 << 1)
  156 +#define LCSR0_BER (1 << 2)
  157 +#define LCSR0_ABC (1 << 3)
  158 +#define LCSR0_IU0 (1 << 4)
  159 +#define LCSR0_IU1 (1 << 5)
  160 +#define LCSR0_OU (1 << 6)
  161 +#define LCSR0_QD (1 << 7)
  162 +#define LCSR0_EOF0 (1 << 8)
  163 +#define LCSR0_BS0 (1 << 9)
  164 +#define LCSR0_SINT (1 << 10)
  165 +#define LCSR0_RDST (1 << 11)
  166 +#define LCSR0_CMDINT (1 << 12)
  167 +#define LCSR0_BERCH(x) (((x) & 7) << 28)
  168 +#define LCSR1_SOF(ch) (1 << (ch - 1))
  169 +#define LCSR1_EOF(ch) (1 << (ch + 7))
  170 +#define LCSR1_BS(ch) (1 << (ch + 15))
  171 +#define LCSR1_IU(ch) (1 << (ch + 23))
  172 +#define LDCMD_LENGTH(x) ((x) & 0x001ffffc)
  173 +#define LDCMD_EOFINT (1 << 21)
  174 +#define LDCMD_SOFINT (1 << 22)
  175 +#define LDCMD_PAL (1 << 26)
  176 +
  177 +/* Route internal interrupt lines to the global IC */
  178 +static void pxa2xx_lcdc_int_update(struct pxa2xx_lcdc_s *s)
  179 +{
  180 + int level = 0;
  181 + level |= (s->status[0] & LCSR0_LDD) && !(s->control[0] & LCCR0_LDM);
  182 + level |= (s->status[0] & LCSR0_SOF0) && !(s->control[0] & LCCR0_SOFM0);
  183 + level |= (s->status[0] & LCSR0_IU0) && !(s->control[0] & LCCR0_IUM);
  184 + level |= (s->status[0] & LCSR0_IU1) && !(s->control[5] & LCCR5_IUM(1));
  185 + level |= (s->status[0] & LCSR0_OU) && !(s->control[0] & LCCR0_OUM);
  186 + level |= (s->status[0] & LCSR0_QD) && !(s->control[0] & LCCR0_QDM);
  187 + level |= (s->status[0] & LCSR0_EOF0) && !(s->control[0] & LCCR0_EOFM0);
  188 + level |= (s->status[0] & LCSR0_BS0) && !(s->control[0] & LCCR0_BSM0);
  189 + level |= (s->status[0] & LCSR0_RDST) && !(s->control[0] & LCCR0_RDSTM);
  190 + level |= (s->status[0] & LCSR0_CMDINT) && !(s->control[0] & LCCR0_CMDIM);
  191 + level |= (s->status[1] & ~s->control[5]);
  192 +
  193 + qemu_set_irq(s->irq, !!level);
  194 + s->irqlevel = level;
  195 +}
  196 +
  197 +/* Set Branch Status interrupt high and poke associated registers */
  198 +static inline void pxa2xx_dma_bs_set(struct pxa2xx_lcdc_s *s, int ch)
  199 +{
  200 + int unmasked;
  201 + if (ch == 0) {
  202 + s->status[0] |= LCSR0_BS0;
  203 + unmasked = !(s->control[0] & LCCR0_BSM0);
  204 + } else {
  205 + s->status[1] |= LCSR1_BS(ch);
  206 + unmasked = !(s->control[5] & LCCR5_BSM(ch));
  207 + }
  208 +
  209 + if (unmasked) {
  210 + if (s->irqlevel)
  211 + s->status[0] |= LCSR0_SINT;
  212 + else
  213 + s->liidr = s->dma_ch[ch].id;
  214 + }
  215 +}
  216 +
  217 +/* Set Start Of Frame Status interrupt high and poke associated registers */
  218 +static inline void pxa2xx_dma_sof_set(struct pxa2xx_lcdc_s *s, int ch)
  219 +{
  220 + int unmasked;
  221 + if (!(s->dma_ch[ch].command & LDCMD_SOFINT))
  222 + return;
  223 +
  224 + if (ch == 0) {
  225 + s->status[0] |= LCSR0_SOF0;
  226 + unmasked = !(s->control[0] & LCCR0_SOFM0);
  227 + } else {
  228 + s->status[1] |= LCSR1_SOF(ch);
  229 + unmasked = !(s->control[5] & LCCR5_SOFM(ch));
  230 + }
  231 +
  232 + if (unmasked) {
  233 + if (s->irqlevel)
  234 + s->status[0] |= LCSR0_SINT;
  235 + else
  236 + s->liidr = s->dma_ch[ch].id;
  237 + }
  238 +}
  239 +
  240 +/* Set End Of Frame Status interrupt high and poke associated registers */
  241 +static inline void pxa2xx_dma_eof_set(struct pxa2xx_lcdc_s *s, int ch)
  242 +{
  243 + int unmasked;
  244 + if (!(s->dma_ch[ch].command & LDCMD_EOFINT))
  245 + return;
  246 +
  247 + if (ch == 0) {
  248 + s->status[0] |= LCSR0_EOF0;
  249 + unmasked = !(s->control[0] & LCCR0_EOFM0);
  250 + } else {
  251 + s->status[1] |= LCSR1_EOF(ch);
  252 + unmasked = !(s->control[5] & LCCR5_EOFM(ch));
  253 + }
  254 +
  255 + if (unmasked) {
  256 + if (s->irqlevel)
  257 + s->status[0] |= LCSR0_SINT;
  258 + else
  259 + s->liidr = s->dma_ch[ch].id;
  260 + }
  261 +}
  262 +
  263 +/* Set Bus Error Status interrupt high and poke associated registers */
  264 +static inline void pxa2xx_dma_ber_set(struct pxa2xx_lcdc_s *s, int ch)
  265 +{
  266 + s->status[0] |= LCSR0_BERCH(ch) | LCSR0_BER;
  267 + if (s->irqlevel)
  268 + s->status[0] |= LCSR0_SINT;
  269 + else
  270 + s->liidr = s->dma_ch[ch].id;
  271 +}
  272 +
  273 +/* Set Read Status interrupt high and poke associated registers */
  274 +static inline void pxa2xx_dma_rdst_set(struct pxa2xx_lcdc_s *s)
  275 +{
  276 + s->status[0] |= LCSR0_RDST;
  277 + if (s->irqlevel && !(s->control[0] & LCCR0_RDSTM))
  278 + s->status[0] |= LCSR0_SINT;
  279 +}
  280 +
  281 +/* Load new Frame Descriptors from DMA */
  282 +static void pxa2xx_descriptor_load(struct pxa2xx_lcdc_s *s)
  283 +{
  284 + struct pxa_frame_descriptor_s *desc[PXA_LCDDMA_CHANS];
  285 + target_phys_addr_t descptr;
  286 + int i;
  287 +
  288 + for (i = 0; i < PXA_LCDDMA_CHANS; i ++) {
  289 + desc[i] = 0;
  290 + s->dma_ch[i].source = 0;
  291 +
  292 + if (!s->dma_ch[i].up)
  293 + continue;
  294 +
  295 + if (s->dma_ch[i].branch & FBR_BRA) {
  296 + descptr = s->dma_ch[i].branch & FBR_SRCADDR;
  297 + if (s->dma_ch[i].branch & FBR_BINT)
  298 + pxa2xx_dma_bs_set(s, i);
  299 + s->dma_ch[i].branch &= ~FBR_BRA;
  300 + } else
  301 + descptr = s->dma_ch[i].descriptor;
  302 +
  303 + if (!(descptr >= PXA2XX_RAM_BASE && descptr +
  304 + sizeof(*desc[i]) <= PXA2XX_RAM_BASE + phys_ram_size))
  305 + continue;
  306 +
  307 + descptr -= PXA2XX_RAM_BASE;
  308 + desc[i] = (struct pxa_frame_descriptor_s *) (phys_ram_base + descptr);
  309 + s->dma_ch[i].descriptor = desc[i]->fdaddr;
  310 + s->dma_ch[i].source = desc[i]->fsaddr;
  311 + s->dma_ch[i].id = desc[i]->fidr;
  312 + s->dma_ch[i].command = desc[i]->ldcmd;
  313 + }
  314 +}
  315 +
  316 +static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
  317 +{
  318 + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
  319 + int ch;
  320 + offset -= s->base;
  321 +
  322 + switch (offset) {
  323 + case LCCR0:
  324 + return s->control[0];
  325 + case LCCR1:
  326 + return s->control[1];
  327 + case LCCR2:
  328 + return s->control[2];
  329 + case LCCR3:
  330 + return s->control[3];
  331 + case LCCR4:
  332 + return s->control[4];
  333 + case LCCR5:
  334 + return s->control[5];
  335 +
  336 + case OVL1C1:
  337 + return s->ovl1c[0];
  338 + case OVL1C2:
  339 + return s->ovl1c[1];
  340 + case OVL2C1:
  341 + return s->ovl2c[0];
  342 + case OVL2C2:
  343 + return s->ovl2c[1];
  344 +
  345 + case CCR:
  346 + return s->ccr;
  347 +
  348 + case CMDCR:
  349 + return s->cmdcr;
  350 +
  351 + case TRGBR:
  352 + return s->trgbr;
  353 + case TCR:
  354 + return s->tcr;
  355 +
  356 + case 0x200 ... 0x1000: /* DMA per-channel registers */
  357 + ch = (offset - 0x200) >> 4;
  358 + if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
  359 + goto fail;
  360 +
  361 + switch (offset & 0xf) {
  362 + case DMA_FDADR:
  363 + return s->dma_ch[ch].descriptor;
  364 + case DMA_FSADR:
  365 + return s->dma_ch[ch].source;
  366 + case DMA_FIDR:
  367 + return s->dma_ch[ch].id;
  368 + case DMA_LDCMD:
  369 + return s->dma_ch[ch].command;
  370 + default:
  371 + goto fail;
  372 + }
  373 +
  374 + case FBR0:
  375 + return s->dma_ch[0].branch;
  376 + case FBR1:
  377 + return s->dma_ch[1].branch;
  378 + case FBR2:
  379 + return s->dma_ch[2].branch;
  380 + case FBR3:
  381 + return s->dma_ch[3].branch;
  382 + case FBR4:
  383 + return s->dma_ch[4].branch;
  384 + case FBR5:
  385 + return s->dma_ch[5].branch;
  386 + case FBR6:
  387 + return s->dma_ch[6].branch;
  388 +
  389 + case BSCNTR:
  390 + return s->bscntr;
  391 +
  392 + case PRSR:
  393 + return 0;
  394 +
  395 + case LCSR0:
  396 + return s->status[0];
  397 + case LCSR1:
  398 + return s->status[1];
  399 + case LIIDR:
  400 + return s->liidr;
  401 +
  402 + default:
  403 + fail:
  404 + cpu_abort(cpu_single_env,
  405 + "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
  406 + }
  407 +
  408 + return 0;
  409 +}
  410 +
  411 +static void pxa2xx_lcdc_write(void *opaque,
  412 + target_phys_addr_t offset, uint32_t value)
  413 +{
  414 + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
  415 + int ch;
  416 + offset -= s->base;
  417 +
  418 + switch (offset) {
  419 + case LCCR0:
  420 + /* ACK Quick Disable done */
  421 + if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB))
  422 + s->status[0] |= LCSR0_QD;
  423 +
  424 + if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT))
  425 + printf("%s: internal frame buffer unsupported\n", __FUNCTION__);
  426 +
  427 + if ((s->control[3] & LCCR3_API) &&
  428 + (value & LCCR0_ENB) && !(value & LCCR0_LCDT))
  429 + s->status[0] |= LCSR0_ABC;
  430 +
  431 + s->control[0] = value & 0x07ffffff;
  432 + pxa2xx_lcdc_int_update(s);
  433 +
  434 + s->dma_ch[0].up = !!(value & LCCR0_ENB);
  435 + s->dma_ch[1].up = (s->ovl1c[0] & OVLC1_EN) || (value & LCCR0_SDS);
  436 + break;
  437 +
  438 + case LCCR1:
  439 + s->control[1] = value;
  440 + break;
  441 +
  442 + case LCCR2:
  443 + s->control[2] = value;
  444 + break;
  445 +
  446 + case LCCR3:
  447 + s->control[3] = value & 0xefffffff;
  448 + s->bpp = LCCR3_BPP(value);
  449 + break;
  450 +
  451 + case LCCR4:
  452 + s->control[4] = value & 0x83ff81ff;
  453 + break;
  454 +
  455 + case LCCR5:
  456 + s->control[5] = value & 0x3f3f3f3f;
  457 + break;
  458 +
  459 + case OVL1C1:
  460 + if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN))
  461 + printf("%s: Overlay 1 not supported\n", __FUNCTION__);
  462 +
  463 + s->ovl1c[0] = value & 0x80ffffff;
  464 + s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS);
  465 + break;
  466 +
  467 + case OVL1C2:
  468 + s->ovl1c[1] = value & 0x000fffff;
  469 + break;
  470 +
  471 + case OVL2C1:
  472 + if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN))
  473 + printf("%s: Overlay 2 not supported\n", __FUNCTION__);
  474 +
  475 + s->ovl2c[0] = value & 0x80ffffff;
  476 + s->dma_ch[2].up = !!(value & OVLC1_EN);
  477 + s->dma_ch[3].up = !!(value & OVLC1_EN);
  478 + s->dma_ch[4].up = !!(value & OVLC1_EN);
  479 + break;
  480 +
  481 + case OVL2C2:
  482 + s->ovl2c[1] = value & 0x007fffff;
  483 + break;
  484 +
  485 + case CCR:
  486 + if (!(s->ccr & CCR_CEN) && (value & CCR_CEN))
  487 + printf("%s: Hardware cursor unimplemented\n", __FUNCTION__);
  488 +
  489 + s->ccr = value & 0x81ffffe7;
  490 + s->dma_ch[5].up = !!(value & CCR_CEN);
  491 + break;
  492 +
  493 + case CMDCR:
  494 + s->cmdcr = value & 0xff;
  495 + break;
  496 +
  497 + case TRGBR:
  498 + s->trgbr = value & 0x00ffffff;
  499 + break;
  500 +
  501 + case TCR:
  502 + s->tcr = value & 0x7fff;
  503 + break;
  504 +
  505 + case 0x200 ... 0x1000: /* DMA per-channel registers */
  506 + ch = (offset - 0x200) >> 4;
  507 + if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
  508 + goto fail;
  509 +
  510 + switch (offset & 0xf) {
  511 + case DMA_FDADR:
  512 + s->dma_ch[ch].descriptor = value & 0xfffffff0;
  513 + break;
  514 +
  515 + default:
  516 + goto fail;
  517 + }
  518 + break;
  519 +
  520 + case FBR0:
  521 + s->dma_ch[0].branch = value & 0xfffffff3;
  522 + break;
  523 + case FBR1:
  524 + s->dma_ch[1].branch = value & 0xfffffff3;
  525 + break;
  526 + case FBR2:
  527 + s->dma_ch[2].branch = value & 0xfffffff3;
  528 + break;
  529 + case FBR3:
  530 + s->dma_ch[3].branch = value & 0xfffffff3;
  531 + break;
  532 + case FBR4:
  533 + s->dma_ch[4].branch = value & 0xfffffff3;
  534 + break;
  535 + case FBR5:
  536 + s->dma_ch[5].branch = value & 0xfffffff3;
  537 + break;
  538 + case FBR6:
  539 + s->dma_ch[6].branch = value & 0xfffffff3;
  540 + break;
  541 +
  542 + case BSCNTR:
  543 + s->bscntr = value & 0xf;
  544 + break;
  545 +
  546 + case PRSR:
  547 + break;
  548 +
  549 + case LCSR0:
  550 + s->status[0] &= ~(value & 0xfff);
  551 + if (value & LCSR0_BER)
  552 + s->status[0] &= ~LCSR0_BERCH(7);
  553 + break;
  554 +
  555 + case LCSR1:
  556 + s->status[1] &= ~(value & 0x3e3f3f);
  557 + break;
  558 +
  559 + default:
  560 + fail:
  561 + cpu_abort(cpu_single_env,
  562 + "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
  563 + }
  564 +}
  565 +
  566 +static CPUReadMemoryFunc *pxa2xx_lcdc_readfn[] = {
  567 + pxa2xx_lcdc_read,
  568 + pxa2xx_lcdc_read,
  569 + pxa2xx_lcdc_read
  570 +};
  571 +
  572 +static CPUWriteMemoryFunc *pxa2xx_lcdc_writefn[] = {
  573 + pxa2xx_lcdc_write,
  574 + pxa2xx_lcdc_write,
  575 + pxa2xx_lcdc_write
  576 +};
  577 +
  578 +static inline
  579 +uint32_t rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
  580 +{
  581 + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
  582 +}
  583 +
  584 +static inline
  585 +uint32_t rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
  586 +{
  587 + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
  588 +}
  589 +
  590 +static inline
  591 +uint32_t rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
  592 +{
  593 + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  594 +}
  595 +
  596 +static inline
  597 +uint32_t rgb_to_pixel24(unsigned int r, unsigned int g, unsigned b)
  598 +{
  599 + return (r << 16) | (g << 8) | b;
  600 +}
  601 +
  602 +static inline
  603 +uint32_t rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
  604 +{
  605 + return (r << 16) | (g << 8) | b;
  606 +}
  607 +
  608 +/* Load new palette for a given DMA channel, convert to internal format */
  609 +static void pxa2xx_palette_parse(struct pxa2xx_lcdc_s *s, int ch, int bpp)
  610 +{
  611 + int i, n, format, r, g, b, alpha;
  612 + uint32_t *dest, *src;
  613 + s->pal_for = LCCR4_PALFOR(s->control[4]);
  614 + format = s->pal_for;
  615 +
  616 + switch (bpp) {
  617 + case pxa_lcdc_2bpp:
  618 + n = 4;
  619 + break;
  620 + case pxa_lcdc_4bpp:
  621 + n = 16;
  622 + break;
  623 + case pxa_lcdc_8bpp:
  624 + n = 256;
  625 + break;
  626 + default:
  627 + format = 0;
  628 + return;
  629 + }
  630 +
  631 + src = (uint32_t *) s->dma_ch[ch].pbuffer;
  632 + dest = (uint32_t *) s->dma_ch[ch].palette;
  633 + alpha = r = g = b = 0;
  634 +
  635 + for (i = 0; i < n; i ++) {
  636 + switch (format) {
  637 + case 0: /* 16 bpp, no transparency */
  638 + alpha = 0;
  639 + if (s->control[0] & LCCR0_CMS)
  640 + r = g = b = *src & 0xff;
  641 + else {
  642 + r = (*src & 0xf800) >> 8;
  643 + g = (*src & 0x07e0) >> 3;
  644 + b = (*src & 0x001f) << 3;
  645 + }
  646 + break;
  647 + case 1: /* 16 bpp plus transparency */
  648 + alpha = *src & (1 << 24);
  649 + if (s->control[0] & LCCR0_CMS)
  650 + r = g = b = *src & 0xff;
  651 + else {
  652 + r = (*src & 0xf800) >> 8;
  653 + g = (*src & 0x07e0) >> 3;
  654 + b = (*src & 0x001f) << 3;
  655 + }
  656 + break;
  657 + case 2: /* 18 bpp plus transparency */
  658 + alpha = *src & (1 << 24);
  659 + if (s->control[0] & LCCR0_CMS)
  660 + r = g = b = *src & 0xff;
  661 + else {
  662 + r = (*src & 0xf80000) >> 16;
  663 + g = (*src & 0x00fc00) >> 8;
  664 + b = (*src & 0x0000f8);
  665 + }
  666 + break;
  667 + case 3: /* 24 bpp plus transparency */
  668 + alpha = *src & (1 << 24);
  669 + if (s->control[0] & LCCR0_CMS)
  670 + r = g = b = *src & 0xff;
  671 + else {
  672 + r = (*src & 0xff0000) >> 16;
  673 + g = (*src & 0x00ff00) >> 8;
  674 + b = (*src & 0x0000ff);
  675 + }
  676 + break;
  677 + }
  678 + switch (s->ds->depth) {
  679 + case 8:
  680 + *dest = rgb_to_pixel8(r, g, b) | alpha;
  681 + break;
  682 + case 15:
  683 + *dest = rgb_to_pixel15(r, g, b) | alpha;
  684 + break;
  685 + case 16:
  686 + *dest = rgb_to_pixel16(r, g, b) | alpha;
  687 + break;
  688 + case 24:
  689 + *dest = rgb_to_pixel24(r, g, b) | alpha;
  690 + break;
  691 + case 32:
  692 + *dest = rgb_to_pixel32(r, g, b) | alpha;
  693 + break;
  694 + }
  695 + src ++;
  696 + dest ++;
  697 + }
  698 +}
  699 +
  700 +static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s,
  701 + uint8_t *fb, int *miny, int *maxy)
  702 +{
  703 + int y, src_width, dest_width, dirty[2];
  704 + uint8_t *src, *dest;
  705 + ram_addr_t x, addr, new_addr, start, end;
  706 + drawfn fn = 0;
  707 + if (s->dest_width)
  708 + fn = s->line_fn[s->transp][s->bpp];
  709 + if (!fn)
  710 + return;
  711 +
  712 + src = fb;
  713 + src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
  714 + if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
  715 + src_width *= 3;
  716 + else if (s->bpp > pxa_lcdc_16bpp)
  717 + src_width *= 4;
  718 + else if (s->bpp > pxa_lcdc_8bpp)
  719 + src_width *= 2;
  720 +
  721 + dest = s->ds->data;
  722 + dest_width = s->xres * s->dest_width;
  723 +
  724 + addr = (ram_addr_t) (fb - phys_ram_base);
  725 + start = addr + s->yres * src_width;
  726 + end = addr;
  727 + dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG);
  728 + for (y = 0; y < s->yres; y ++) {
  729 + new_addr = addr + src_width;
  730 + for (x = addr + TARGET_PAGE_SIZE; x < new_addr;
  731 + x += TARGET_PAGE_SIZE) {
  732 + dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG);
  733 + dirty[0] |= dirty[1];
  734 + }
  735 + if (dirty[0] || s->invalidated) {
  736 + fn((uint32_t *) s->dma_ch[0].palette,
  737 + dest, src, s->xres, s->dest_width);
  738 + if (addr < start)
  739 + start = addr;
  740 + if (new_addr > end)
  741 + end = new_addr;
  742 + if (y < *miny)
  743 + *miny = y;
  744 + if (y >= *maxy)
  745 + *maxy = y + 1;
  746 + }
  747 + addr = new_addr;
  748 + dirty[0] = dirty[1];
  749 + src += src_width;
  750 + dest += dest_width;
  751 + }
  752 +
  753 + if (end > start)
  754 + cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
  755 +}
  756 +
  757 +static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s,
  758 + uint8_t *fb, int *miny, int *maxy)
  759 +{
  760 + int y, src_width, dest_width, dirty[2];
  761 + uint8_t *src, *dest;
  762 + ram_addr_t x, addr, new_addr, start, end;
  763 + drawfn fn = 0;
  764 + if (s->dest_width)
  765 + fn = s->line_fn[s->transp][s->bpp];
  766 + if (!fn)
  767 + return;
  768 +
  769 + src = fb;
  770 + src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
  771 + if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
  772 + src_width *= 3;
  773 + else if (s->bpp > pxa_lcdc_16bpp)
  774 + src_width *= 4;
  775 + else if (s->bpp > pxa_lcdc_8bpp)
  776 + src_width *= 2;
  777 +
  778 + dest_width = s->yres * s->dest_width;
  779 + dest = s->ds->data + dest_width * (s->xres - 1);
  780 +
  781 + addr = (ram_addr_t) (fb - phys_ram_base);
  782 + start = addr + s->yres * src_width;
  783 + end = addr;
  784 + dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG);
  785 + for (y = 0; y < s->yres; y ++) {
  786 + new_addr = addr + src_width;
  787 + for (x = addr + TARGET_PAGE_SIZE; x < new_addr;
  788 + x += TARGET_PAGE_SIZE) {
  789 + dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG);
  790 + dirty[0] |= dirty[1];
  791 + }
  792 + if (dirty[0] || s->invalidated) {
  793 + fn((uint32_t *) s->dma_ch[0].palette,
  794 + dest, src, s->xres, -dest_width);
  795 + if (addr < start)
  796 + start = addr;
  797 + if (new_addr > end)
  798 + end = new_addr;
  799 + if (y < *miny)
  800 + *miny = y;
  801 + if (y >= *maxy)
  802 + *maxy = y + 1;
  803 + }
  804 + addr = new_addr;
  805 + dirty[0] = dirty[1];
  806 + src += src_width;
  807 + dest += s->dest_width;
  808 + }
  809 +
  810 + if (end > start)
  811 + cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
  812 +}
  813 +
  814 +static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s)
  815 +{
  816 + int width, height;
  817 + if (!(s->control[0] & LCCR0_ENB))
  818 + return;
  819 +
  820 + width = LCCR1_PPL(s->control[1]) + 1;
  821 + height = LCCR2_LPP(s->control[2]) + 1;
  822 +
  823 + if (width != s->xres || height != s->yres) {
  824 + if (s->orientation)
  825 + dpy_resize(s->ds, height, width);
  826 + else
  827 + dpy_resize(s->ds, width, height);
  828 + s->invalidated = 1;
  829 + s->xres = width;
  830 + s->yres = height;
  831 + }
  832 +}
  833 +
  834 +static void pxa2xx_update_display(void *opaque)
  835 +{
  836 + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
  837 + uint8_t *fb;
  838 + target_phys_addr_t fbptr;
  839 + int miny, maxy;
  840 + int ch;
  841 + if (!(s->control[0] & LCCR0_ENB))
  842 + return;
  843 +
  844 + pxa2xx_descriptor_load(s);
  845 +
  846 + pxa2xx_lcdc_resize(s);
  847 + miny = s->yres;
  848 + maxy = 0;
  849 + s->transp = s->dma_ch[2].up || s->dma_ch[3].up;
  850 + /* Note: With overlay planes the order depends on LCCR0 bit 25. */
  851 + for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++)
  852 + if (s->dma_ch[ch].up) {
  853 + if (!s->dma_ch[ch].source) {
  854 + pxa2xx_dma_ber_set(s, ch);
  855 + continue;
  856 + }
  857 + fbptr = s->dma_ch[ch].source;
  858 + if (!(fbptr >= PXA2XX_RAM_BASE &&
  859 + fbptr <= PXA2XX_RAM_BASE + phys_ram_size)) {
  860 + pxa2xx_dma_ber_set(s, ch);
  861 + continue;
  862 + }
  863 + fbptr -= PXA2XX_RAM_BASE;
  864 + fb = phys_ram_base + fbptr;
  865 +
  866 + if (s->dma_ch[ch].command & LDCMD_PAL) {
  867 + memcpy(s->dma_ch[ch].pbuffer, fb,
  868 + MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
  869 + sizeof(s->dma_ch[ch].pbuffer)));
  870 + pxa2xx_palette_parse(s, ch, s->bpp);
  871 + } else {
  872 + /* Do we need to reparse palette */
  873 + if (LCCR4_PALFOR(s->control[4]) != s->pal_for)
  874 + pxa2xx_palette_parse(s, ch, s->bpp);
  875 +
  876 + /* ACK frame start */
  877 + pxa2xx_dma_sof_set(s, ch);
  878 +
  879 + s->dma_ch[ch].redraw(s, fb, &miny, &maxy);
  880 + s->invalidated = 0;
  881 +
  882 + /* ACK frame completed */
  883 + pxa2xx_dma_eof_set(s, ch);
  884 + }
  885 + }
  886 +
  887 + if (s->control[0] & LCCR0_DIS) {
  888 + /* ACK last frame completed */
  889 + s->control[0] &= ~LCCR0_ENB;
  890 + s->status[0] |= LCSR0_LDD;
  891 + }
  892 +
  893 + if (s->orientation)
  894 + dpy_update(s->ds, miny, 0, maxy, s->xres);
  895 + else
  896 + dpy_update(s->ds, 0, miny, s->xres, maxy);
  897 + pxa2xx_lcdc_int_update(s);
  898 +
  899 + if (s->vsync_cb)
  900 + s->vsync_cb(s->opaque);
  901 +}
  902 +
  903 +static void pxa2xx_invalidate_display(void *opaque)
  904 +{
  905 + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
  906 + s->invalidated = 1;
  907 +}
  908 +
  909 +static void pxa2xx_screen_dump(void *opaque, const char *filename)
  910 +{
  911 + /* TODO */
  912 +}
  913 +
  914 +void pxa2xx_lcdc_orientation(void *opaque, int angle)
  915 +{
  916 + struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
  917 +
  918 + if (angle) {
  919 + s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
  920 + } else {
  921 + s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
  922 + }
  923 +
  924 + s->orientation = angle;
  925 + s->xres = s->yres = -1;
  926 + pxa2xx_lcdc_resize(s);
  927 +}
  928 +
  929 +#define BITS 8
  930 +#include "pxa2xx_template.h"
  931 +#define BITS 15
  932 +#include "pxa2xx_template.h"
  933 +#define BITS 16
  934 +#include "pxa2xx_template.h"
  935 +#define BITS 24
  936 +#include "pxa2xx_template.h"
  937 +#define BITS 32
  938 +#include "pxa2xx_template.h"
  939 +
  940 +struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq,
  941 + DisplayState *ds)
  942 +{
  943 + int iomemtype;
  944 + struct pxa2xx_lcdc_s *s;
  945 +
  946 + s = (struct pxa2xx_lcdc_s *) qemu_mallocz(sizeof(struct pxa2xx_lcdc_s));
  947 + s->base = base;
  948 + s->invalidated = 1;
  949 + s->irq = irq;
  950 + s->ds = ds;
  951 +
  952 + pxa2xx_lcdc_orientation(s, graphic_rotate);
  953 +
  954 + iomemtype = cpu_register_io_memory(0, pxa2xx_lcdc_readfn,
  955 + pxa2xx_lcdc_writefn, s);
  956 + cpu_register_physical_memory(base, 0x000fffff, iomemtype);
  957 +
  958 + graphic_console_init(ds, pxa2xx_update_display,
  959 + pxa2xx_invalidate_display, pxa2xx_screen_dump, s);
  960 +
  961 + switch (s->ds->depth) {
  962 + case 0:
  963 + s->dest_width = 0;
  964 + break;
  965 + case 8:
  966 + s->line_fn[0] = pxa2xx_draw_fn_8;
  967 + s->line_fn[1] = pxa2xx_draw_fn_8t;
  968 + s->dest_width = 1;
  969 + break;
  970 + case 15:
  971 + s->line_fn[0] = pxa2xx_draw_fn_15;
  972 + s->line_fn[1] = pxa2xx_draw_fn_15t;
  973 + s->dest_width = 2;
  974 + break;
  975 + case 16:
  976 + s->line_fn[0] = pxa2xx_draw_fn_16;
  977 + s->line_fn[1] = pxa2xx_draw_fn_16t;
  978 + s->dest_width = 2;
  979 + break;
  980 + case 24:
  981 + s->line_fn[0] = pxa2xx_draw_fn_24;
  982 + s->line_fn[1] = pxa2xx_draw_fn_24t;
  983 + s->dest_width = 3;
  984 + break;
  985 + case 32:
  986 + s->line_fn[0] = pxa2xx_draw_fn_32;
  987 + s->line_fn[1] = pxa2xx_draw_fn_32t;
  988 + s->dest_width = 4;
  989 + break;
  990 + default:
  991 + fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
  992 + exit(1);
  993 + }
  994 + return s;
  995 +}
  996 +
  997 +void pxa2xx_lcd_vsync_cb(struct pxa2xx_lcdc_s *s,
  998 + void (*cb)(void *opaque), void *opaque) {
  999 + s->vsync_cb = cb;
  1000 + s->opaque = opaque;
  1001 +}
... ...
hw/pxa2xx_mmci.c 0 โ†’ 100644
  1 +/*
  2 + * Intel XScale PXA255/270 MultiMediaCard/SD/SDIO Controller emulation.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  6 + *
  7 + * This code is licensed under the GPLv2.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +#include "sd.h"
  12 +
  13 +struct pxa2xx_mmci_s {
  14 + target_phys_addr_t base;
  15 + qemu_irq irq;
  16 + void *dma;
  17 +
  18 + SDState *card;
  19 +
  20 + uint32_t status;
  21 + uint32_t clkrt;
  22 + uint32_t spi;
  23 + uint32_t cmdat;
  24 + uint32_t resp_tout;
  25 + uint32_t read_tout;
  26 + int blklen;
  27 + int numblk;
  28 + uint32_t intmask;
  29 + uint32_t intreq;
  30 + int cmd;
  31 + uint32_t arg;
  32 +
  33 + int active;
  34 + int bytesleft;
  35 + uint8_t tx_fifo[64];
  36 + int tx_start;
  37 + int tx_len;
  38 + uint8_t rx_fifo[32];
  39 + int rx_start;
  40 + int rx_len;
  41 + uint16_t resp_fifo[9];
  42 + int resp_len;
  43 +
  44 + int cmdreq;
  45 + int ac_width;
  46 +};
  47 +
  48 +#define MMC_STRPCL 0x00 /* MMC Clock Start/Stop register */
  49 +#define MMC_STAT 0x04 /* MMC Status register */
  50 +#define MMC_CLKRT 0x08 /* MMC Clock Rate register */
  51 +#define MMC_SPI 0x0c /* MMC SPI Mode register */
  52 +#define MMC_CMDAT 0x10 /* MMC Command/Data register */
  53 +#define MMC_RESTO 0x14 /* MMC Response Time-Out register */
  54 +#define MMC_RDTO 0x18 /* MMC Read Time-Out register */
  55 +#define MMC_BLKLEN 0x1c /* MMC Block Length register */
  56 +#define MMC_NUMBLK 0x20 /* MMC Number of Blocks register */
  57 +#define MMC_PRTBUF 0x24 /* MMC Buffer Partly Full register */
  58 +#define MMC_I_MASK 0x28 /* MMC Interrupt Mask register */
  59 +#define MMC_I_REG 0x2c /* MMC Interrupt Request register */
  60 +#define MMC_CMD 0x30 /* MMC Command register */
  61 +#define MMC_ARGH 0x34 /* MMC Argument High register */
  62 +#define MMC_ARGL 0x38 /* MMC Argument Low register */
  63 +#define MMC_RES 0x3c /* MMC Response FIFO */
  64 +#define MMC_RXFIFO 0x40 /* MMC Receive FIFO */
  65 +#define MMC_TXFIFO 0x44 /* MMC Transmit FIFO */
  66 +#define MMC_RDWAIT 0x48 /* MMC RD_WAIT register */
  67 +#define MMC_BLKS_REM 0x4c /* MMC Blocks Remaining register */
  68 +
  69 +/* Bitfield masks */
  70 +#define STRPCL_STOP_CLK (1 << 0)
  71 +#define STRPCL_STRT_CLK (1 << 1)
  72 +#define STAT_TOUT_RES (1 << 1)
  73 +#define STAT_CLK_EN (1 << 8)
  74 +#define STAT_DATA_DONE (1 << 11)
  75 +#define STAT_PRG_DONE (1 << 12)
  76 +#define STAT_END_CMDRES (1 << 13)
  77 +#define SPI_SPI_MODE (1 << 0)
  78 +#define CMDAT_RES_TYPE (3 << 0)
  79 +#define CMDAT_DATA_EN (1 << 2)
  80 +#define CMDAT_WR_RD (1 << 3)
  81 +#define CMDAT_DMA_EN (1 << 7)
  82 +#define CMDAT_STOP_TRAN (1 << 10)
  83 +#define INT_DATA_DONE (1 << 0)
  84 +#define INT_PRG_DONE (1 << 1)
  85 +#define INT_END_CMD (1 << 2)
  86 +#define INT_STOP_CMD (1 << 3)
  87 +#define INT_CLK_OFF (1 << 4)
  88 +#define INT_RXFIFO_REQ (1 << 5)
  89 +#define INT_TXFIFO_REQ (1 << 6)
  90 +#define INT_TINT (1 << 7)
  91 +#define INT_DAT_ERR (1 << 8)
  92 +#define INT_RES_ERR (1 << 9)
  93 +#define INT_RD_STALLED (1 << 10)
  94 +#define INT_SDIO_INT (1 << 11)
  95 +#define INT_SDIO_SACK (1 << 12)
  96 +#define PRTBUF_PRT_BUF (1 << 0)
  97 +
  98 +/* Route internal interrupt lines to the global IC and DMA */
  99 +static void pxa2xx_mmci_int_update(struct pxa2xx_mmci_s *s)
  100 +{
  101 + uint32_t mask = s->intmask;
  102 + if (s->cmdat & CMDAT_DMA_EN) {
  103 + mask |= INT_RXFIFO_REQ | INT_TXFIFO_REQ;
  104 +
  105 + pxa2xx_dma_request((struct pxa2xx_dma_state_s *) s->dma,
  106 + PXA2XX_RX_RQ_MMCI, !!(s->intreq & INT_RXFIFO_REQ));
  107 + pxa2xx_dma_request((struct pxa2xx_dma_state_s *) s->dma,
  108 + PXA2XX_TX_RQ_MMCI, !!(s->intreq & INT_TXFIFO_REQ));
  109 + }
  110 +
  111 + qemu_set_irq(s->irq, !!(s->intreq & ~mask));
  112 +}
  113 +
  114 +static void pxa2xx_mmci_fifo_update(struct pxa2xx_mmci_s *s)
  115 +{
  116 + if (!s->active)
  117 + return;
  118 +
  119 + if (s->cmdat & CMDAT_WR_RD) {
  120 + while (s->bytesleft && s->tx_len) {
  121 + sd_write_data(s->card, s->tx_fifo[s->tx_start ++]);
  122 + s->tx_start &= 0x1f;
  123 + s->tx_len --;
  124 + s->bytesleft --;
  125 + }
  126 + if (s->bytesleft)
  127 + s->intreq |= INT_TXFIFO_REQ;
  128 + } else
  129 + while (s->bytesleft && s->rx_len < 32) {
  130 + s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
  131 + sd_read_data(s->card);
  132 + s->bytesleft --;
  133 + s->intreq |= INT_RXFIFO_REQ;
  134 + }
  135 +
  136 + if (!s->bytesleft) {
  137 + s->active = 0;
  138 + s->intreq |= INT_DATA_DONE;
  139 + s->status |= STAT_DATA_DONE;
  140 +
  141 + if (s->cmdat & CMDAT_WR_RD) {
  142 + s->intreq |= INT_PRG_DONE;
  143 + s->status |= STAT_PRG_DONE;
  144 + }
  145 + }
  146 +
  147 + pxa2xx_mmci_int_update(s);
  148 +}
  149 +
  150 +static void pxa2xx_mmci_wakequeues(struct pxa2xx_mmci_s *s)
  151 +{
  152 + int rsplen, i;
  153 + struct sd_request_s request;
  154 + uint8_t response[16];
  155 +
  156 + s->active = 1;
  157 + s->rx_len = 0;
  158 + s->tx_len = 0;
  159 + s->cmdreq = 0;
  160 +
  161 + request.cmd = s->cmd;
  162 + request.arg = s->arg;
  163 + request.crc = 0; /* FIXME */
  164 +
  165 + rsplen = sd_do_command(s->card, &request, response);
  166 + s->intreq |= INT_END_CMD;
  167 +
  168 + memset(s->resp_fifo, 0, sizeof(s->resp_fifo));
  169 + switch (s->cmdat & CMDAT_RES_TYPE) {
  170 +#define PXAMMCI_RESP(wd, value0, value1) \
  171 + s->resp_fifo[(wd) + 0] |= (value0); \
  172 + s->resp_fifo[(wd) + 1] |= (value1) << 8;
  173 + case 0: /* No response */
  174 + goto complete;
  175 +
  176 + case 1: /* R1, R4, R5 or R6 */
  177 + if (rsplen < 4)
  178 + goto timeout;
  179 + goto complete;
  180 +
  181 + case 2: /* R2 */
  182 + if (rsplen < 16)
  183 + goto timeout;
  184 + goto complete;
  185 +
  186 + case 3: /* R3 */
  187 + if (rsplen < 4)
  188 + goto timeout;
  189 + goto complete;
  190 +
  191 + complete:
  192 + for (i = 0; rsplen > 0; i ++, rsplen -= 2) {
  193 + PXAMMCI_RESP(i, response[i * 2], response[i * 2 + 1]);
  194 + }
  195 + s->status |= STAT_END_CMDRES;
  196 +
  197 + if (!(s->cmdat & CMDAT_DATA_EN))
  198 + s->active = 0;
  199 + else
  200 + s->bytesleft = s->numblk * s->blklen;
  201 +
  202 + s->resp_len = 0;
  203 + break;
  204 +
  205 + timeout:
  206 + s->active = 0;
  207 + s->status |= STAT_TOUT_RES;
  208 + break;
  209 + }
  210 +
  211 + pxa2xx_mmci_fifo_update(s);
  212 +}
  213 +
  214 +static uint32_t pxa2xx_mmci_read(void *opaque, target_phys_addr_t offset)
  215 +{
  216 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  217 + uint32_t ret;
  218 + offset -= s->base;
  219 +
  220 + switch (offset) {
  221 + case MMC_STRPCL:
  222 + return 0;
  223 + case MMC_STAT:
  224 + return s->status;
  225 + case MMC_CLKRT:
  226 + return s->clkrt;
  227 + case MMC_SPI:
  228 + return s->spi;
  229 + case MMC_CMDAT:
  230 + return s->cmdat;
  231 + case MMC_RESTO:
  232 + return s->resp_tout;
  233 + case MMC_RDTO:
  234 + return s->read_tout;
  235 + case MMC_BLKLEN:
  236 + return s->blklen;
  237 + case MMC_NUMBLK:
  238 + return s->numblk;
  239 + case MMC_PRTBUF:
  240 + return 0;
  241 + case MMC_I_MASK:
  242 + return s->intmask;
  243 + case MMC_I_REG:
  244 + return s->intreq;
  245 + case MMC_CMD:
  246 + return s->cmd | 0x40;
  247 + case MMC_ARGH:
  248 + return s->arg >> 16;
  249 + case MMC_ARGL:
  250 + return s->arg & 0xffff;
  251 + case MMC_RES:
  252 + if (s->resp_len < 9)
  253 + return s->resp_fifo[s->resp_len ++];
  254 + return 0;
  255 + case MMC_RXFIFO:
  256 + ret = 0;
  257 + while (s->ac_width -- && s->rx_len) {
  258 + ret |= s->rx_fifo[s->rx_start ++] << (s->ac_width << 3);
  259 + s->rx_start &= 0x1f;
  260 + s->rx_len --;
  261 + }
  262 + s->intreq &= ~INT_RXFIFO_REQ;
  263 + pxa2xx_mmci_fifo_update(s);
  264 + return ret;
  265 + case MMC_RDWAIT:
  266 + return 0;
  267 + case MMC_BLKS_REM:
  268 + return s->numblk;
  269 + default:
  270 + cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
  271 + __FUNCTION__, offset);
  272 + }
  273 +
  274 + return 0;
  275 +}
  276 +
  277 +static void pxa2xx_mmci_write(void *opaque,
  278 + target_phys_addr_t offset, uint32_t value)
  279 +{
  280 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  281 + offset -= s->base;
  282 +
  283 + switch (offset) {
  284 + case MMC_STRPCL:
  285 + if (value & STRPCL_STRT_CLK) {
  286 + s->status |= STAT_CLK_EN;
  287 + s->intreq &= ~INT_CLK_OFF;
  288 +
  289 + if (s->cmdreq && !(s->cmdat & CMDAT_STOP_TRAN)) {
  290 + s->status &= STAT_CLK_EN;
  291 + pxa2xx_mmci_wakequeues(s);
  292 + }
  293 + }
  294 +
  295 + if (value & STRPCL_STOP_CLK) {
  296 + s->status &= ~STAT_CLK_EN;
  297 + s->intreq |= INT_CLK_OFF;
  298 + s->active = 0;
  299 + }
  300 +
  301 + pxa2xx_mmci_int_update(s);
  302 + break;
  303 +
  304 + case MMC_CLKRT:
  305 + s->clkrt = value & 7;
  306 + break;
  307 +
  308 + case MMC_SPI:
  309 + s->spi = value & 0xf;
  310 + if (value & SPI_SPI_MODE)
  311 + printf("%s: attempted to use card in SPI mode\n", __FUNCTION__);
  312 + break;
  313 +
  314 + case MMC_CMDAT:
  315 + s->cmdat = value & 0x3dff;
  316 + s->active = 0;
  317 + s->cmdreq = 1;
  318 + if (!(value & CMDAT_STOP_TRAN)) {
  319 + s->status &= STAT_CLK_EN;
  320 +
  321 + if (s->status & STAT_CLK_EN)
  322 + pxa2xx_mmci_wakequeues(s);
  323 + }
  324 +
  325 + pxa2xx_mmci_int_update(s);
  326 + break;
  327 +
  328 + case MMC_RESTO:
  329 + s->resp_tout = value & 0x7f;
  330 + break;
  331 +
  332 + case MMC_RDTO:
  333 + s->read_tout = value & 0xffff;
  334 + break;
  335 +
  336 + case MMC_BLKLEN:
  337 + s->blklen = value & 0xfff;
  338 + break;
  339 +
  340 + case MMC_NUMBLK:
  341 + s->numblk = value & 0xffff;
  342 + break;
  343 +
  344 + case MMC_PRTBUF:
  345 + if (value & PRTBUF_PRT_BUF) {
  346 + s->tx_start ^= 32;
  347 + s->tx_len = 0;
  348 + }
  349 + pxa2xx_mmci_fifo_update(s);
  350 + break;
  351 +
  352 + case MMC_I_MASK:
  353 + s->intmask = value & 0x1fff;
  354 + pxa2xx_mmci_int_update(s);
  355 + break;
  356 +
  357 + case MMC_CMD:
  358 + s->cmd = value & 0x3f;
  359 + break;
  360 +
  361 + case MMC_ARGH:
  362 + s->arg &= 0x0000ffff;
  363 + s->arg |= value << 16;
  364 + break;
  365 +
  366 + case MMC_ARGL:
  367 + s->arg &= 0xffff0000;
  368 + s->arg |= value & 0x0000ffff;
  369 + break;
  370 +
  371 + case MMC_TXFIFO:
  372 + while (s->ac_width -- && s->tx_len < 0x20)
  373 + s->tx_fifo[(s->tx_start + (s->tx_len ++)) & 0x1f] =
  374 + (value >> (s->ac_width << 3)) & 0xff;
  375 + s->intreq &= ~INT_TXFIFO_REQ;
  376 + pxa2xx_mmci_fifo_update(s);
  377 + break;
  378 +
  379 + case MMC_RDWAIT:
  380 + case MMC_BLKS_REM:
  381 + break;
  382 +
  383 + default:
  384 + cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
  385 + __FUNCTION__, offset);
  386 + }
  387 +}
  388 +
  389 +static uint32_t pxa2xx_mmci_readb(void *opaque, target_phys_addr_t offset)
  390 +{
  391 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  392 + s->ac_width = 1;
  393 + return pxa2xx_mmci_read(opaque, offset);
  394 +}
  395 +
  396 +static uint32_t pxa2xx_mmci_readh(void *opaque, target_phys_addr_t offset)
  397 +{
  398 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  399 + s->ac_width = 2;
  400 + return pxa2xx_mmci_read(opaque, offset);
  401 +}
  402 +
  403 +static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset)
  404 +{
  405 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  406 + s->ac_width = 4;
  407 + return pxa2xx_mmci_read(opaque, offset);
  408 +}
  409 +
  410 +static CPUReadMemoryFunc *pxa2xx_mmci_readfn[] = {
  411 + pxa2xx_mmci_readb,
  412 + pxa2xx_mmci_readh,
  413 + pxa2xx_mmci_readw
  414 +};
  415 +
  416 +static void pxa2xx_mmci_writeb(void *opaque,
  417 + target_phys_addr_t offset, uint32_t value)
  418 +{
  419 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  420 + s->ac_width = 1;
  421 + pxa2xx_mmci_write(opaque, offset, value);
  422 +}
  423 +
  424 +static void pxa2xx_mmci_writeh(void *opaque,
  425 + target_phys_addr_t offset, uint32_t value)
  426 +{
  427 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  428 + s->ac_width = 2;
  429 + pxa2xx_mmci_write(opaque, offset, value);
  430 +}
  431 +
  432 +static void pxa2xx_mmci_writew(void *opaque,
  433 + target_phys_addr_t offset, uint32_t value)
  434 +{
  435 + struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
  436 + s->ac_width = 4;
  437 + pxa2xx_mmci_write(opaque, offset, value);
  438 +}
  439 +
  440 +static CPUWriteMemoryFunc *pxa2xx_mmci_writefn[] = {
  441 + pxa2xx_mmci_writeb,
  442 + pxa2xx_mmci_writeh,
  443 + pxa2xx_mmci_writew
  444 +};
  445 +
  446 +struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
  447 + qemu_irq irq, void *dma)
  448 +{
  449 + int iomemtype;
  450 + struct pxa2xx_mmci_s *s;
  451 +
  452 + s = (struct pxa2xx_mmci_s *) qemu_mallocz(sizeof(struct pxa2xx_mmci_s));
  453 + s->base = base;
  454 + s->irq = irq;
  455 + s->dma = dma;
  456 +
  457 + iomemtype = cpu_register_io_memory(0, pxa2xx_mmci_readfn,
  458 + pxa2xx_mmci_writefn, s);
  459 + cpu_register_physical_memory(base, 0x000fffff, iomemtype);
  460 +
  461 + /* Instantiate the actual storage */
  462 + s->card = sd_init(sd_bdrv);
  463 +
  464 + return s;
  465 +}
  466 +
  467 +void pxa2xx_mmci_handlers(struct pxa2xx_mmci_s *s, void *opaque,
  468 + void (*readonly_cb)(void *, int),
  469 + void (*coverswitch_cb)(void *, int))
  470 +{
  471 + sd_set_cb(s->card, opaque, readonly_cb, coverswitch_cb);
  472 +}
... ...
hw/pxa2xx_pcmcia.c 0 โ†’ 100644
  1 +/*
  2 + * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  6 + *
  7 + * This code is licensed under the GPLv2.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +struct pxa2xx_pcmcia_s {
  13 + struct pcmcia_socket_s slot;
  14 + struct pcmcia_card_s *card;
  15 + target_phys_addr_t common_base;
  16 + target_phys_addr_t attr_base;
  17 + target_phys_addr_t io_base;
  18 +
  19 + qemu_irq irq;
  20 + qemu_irq cd_irq;
  21 +};
  22 +
  23 +static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
  24 + target_phys_addr_t offset)
  25 +{
  26 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  27 +
  28 + if (s->slot.attached) {
  29 + offset -= s->common_base;
  30 + return s->card->common_read(s->card->state, offset);
  31 + }
  32 +
  33 + return 0;
  34 +}
  35 +
  36 +static void pxa2xx_pcmcia_common_write(void *opaque,
  37 + target_phys_addr_t offset, uint32_t value)
  38 +{
  39 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  40 +
  41 + if (s->slot.attached) {
  42 + offset -= s->common_base;
  43 + s->card->common_write(s->card->state, offset, value);
  44 + }
  45 +}
  46 +
  47 +static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
  48 + target_phys_addr_t offset)
  49 +{
  50 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  51 +
  52 + if (s->slot.attached) {
  53 + offset -= s->attr_base;
  54 + return s->card->attr_read(s->card->state, offset);
  55 + }
  56 +
  57 + return 0;
  58 +}
  59 +
  60 +static void pxa2xx_pcmcia_attr_write(void *opaque,
  61 + target_phys_addr_t offset, uint32_t value)
  62 +{
  63 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  64 +
  65 + if (s->slot.attached) {
  66 + offset -= s->attr_base;
  67 + s->card->attr_write(s->card->state, offset, value);
  68 + }
  69 +}
  70 +
  71 +static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
  72 + target_phys_addr_t offset)
  73 +{
  74 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  75 +
  76 + if (s->slot.attached) {
  77 + offset -= s->io_base;
  78 + return s->card->io_read(s->card->state, offset);
  79 + }
  80 +
  81 + return 0;
  82 +}
  83 +
  84 +static void pxa2xx_pcmcia_io_write(void *opaque,
  85 + target_phys_addr_t offset, uint32_t value)
  86 +{
  87 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  88 +
  89 + if (s->slot.attached) {
  90 + offset -= s->io_base;
  91 + s->card->io_write(s->card->state, offset, value);
  92 + }
  93 +}
  94 +
  95 +static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
  96 + pxa2xx_pcmcia_common_read,
  97 + pxa2xx_pcmcia_common_read,
  98 + pxa2xx_pcmcia_common_read,
  99 +};
  100 +
  101 +static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
  102 + pxa2xx_pcmcia_common_write,
  103 + pxa2xx_pcmcia_common_write,
  104 + pxa2xx_pcmcia_common_write,
  105 +};
  106 +
  107 +static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
  108 + pxa2xx_pcmcia_attr_read,
  109 + pxa2xx_pcmcia_attr_read,
  110 + pxa2xx_pcmcia_attr_read,
  111 +};
  112 +
  113 +static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
  114 + pxa2xx_pcmcia_attr_write,
  115 + pxa2xx_pcmcia_attr_write,
  116 + pxa2xx_pcmcia_attr_write,
  117 +};
  118 +
  119 +static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
  120 + pxa2xx_pcmcia_io_read,
  121 + pxa2xx_pcmcia_io_read,
  122 + pxa2xx_pcmcia_io_read,
  123 +};
  124 +
  125 +static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
  126 + pxa2xx_pcmcia_io_write,
  127 + pxa2xx_pcmcia_io_write,
  128 + pxa2xx_pcmcia_io_write,
  129 +};
  130 +
  131 +static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
  132 +{
  133 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  134 + if (!s->irq)
  135 + return;
  136 +
  137 + qemu_set_irq(s->irq, level);
  138 +}
  139 +
  140 +struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
  141 +{
  142 + int iomemtype;
  143 + struct pxa2xx_pcmcia_s *s;
  144 +
  145 + s = (struct pxa2xx_pcmcia_s *)
  146 + qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
  147 +
  148 + /* Socket I/O Memory Space */
  149 + s->io_base = base | 0x00000000;
  150 + iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
  151 + pxa2xx_pcmcia_io_writefn, s);
  152 + cpu_register_physical_memory(s->io_base, 0x03ffffff, iomemtype);
  153 +
  154 + /* Then next 64 MB is reserved */
  155 +
  156 + /* Socket Attribute Memory Space */
  157 + s->attr_base = base | 0x08000000;
  158 + iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
  159 + pxa2xx_pcmcia_attr_writefn, s);
  160 + cpu_register_physical_memory(s->attr_base, 0x03ffffff, iomemtype);
  161 +
  162 + /* Socket Common Memory Space */
  163 + s->common_base = base | 0x0c000000;
  164 + iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
  165 + pxa2xx_pcmcia_common_writefn, s);
  166 + cpu_register_physical_memory(s->common_base, 0x03ffffff, iomemtype);
  167 +
  168 + if (base == 0x30000000)
  169 + s->slot.slot_string = "PXA PC Card Socket 1";
  170 + else
  171 + s->slot.slot_string = "PXA PC Card Socket 0";
  172 + s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
  173 + pcmcia_socket_register(&s->slot);
  174 + return s;
  175 +}
  176 +
  177 +/* Insert a new card into a slot */
  178 +int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
  179 +{
  180 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  181 + if (s->slot.attached)
  182 + return -EEXIST;
  183 +
  184 + if (s->cd_irq) {
  185 + qemu_irq_raise(s->cd_irq);
  186 + }
  187 +
  188 + s->card = card;
  189 +
  190 + s->slot.attached = 1;
  191 + s->card->slot = &s->slot;
  192 + s->card->attach(s->card->state);
  193 +
  194 + return 0;
  195 +}
  196 +
  197 +/* Eject card from the slot */
  198 +int pxa2xx_pcmcia_dettach(void *opaque)
  199 +{
  200 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  201 + if (!s->slot.attached)
  202 + return -ENOENT;
  203 +
  204 + s->card->detach(s->card->state);
  205 + s->card->slot = 0;
  206 + s->card = 0;
  207 +
  208 + s->slot.attached = 0;
  209 +
  210 + if (s->irq)
  211 + qemu_irq_lower(s->irq);
  212 + if (s->cd_irq)
  213 + qemu_irq_lower(s->cd_irq);
  214 +
  215 + return 0;
  216 +}
  217 +
  218 +/* Who to notify on card events */
  219 +void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
  220 +{
  221 + struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  222 + s->irq = irq;
  223 + s->cd_irq = cd_irq;
  224 +}
... ...
hw/pxa2xx_template.h 0 โ†’ 100644
  1 +/*
  2 + * Intel XScale PXA255/270 LCDC emulation.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  6 + *
  7 + * This code is licensed under the GPLv2.
  8 + *
  9 + * Framebuffer format conversion routines.
  10 + */
  11 +
  12 +# define SKIP_PIXEL(to) to += deststep
  13 +#if BITS == 8
  14 +# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
  15 +#elif BITS == 15 || BITS == 16
  16 +# define COPY_PIXEL(to, from) *(uint16_t *) to = from; SKIP_PIXEL(to)
  17 +#elif BITS == 24
  18 +# define COPY_PIXEL(to, from) \
  19 + *(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to)
  20 +#elif BITS == 32
  21 +# define COPY_PIXEL(to, from) *(uint32_t *) to = from; SKIP_PIXEL(to)
  22 +#else
  23 +# error unknown bit depth
  24 +#endif
  25 +
  26 +#ifdef WORDS_BIGENDIAN
  27 +# define SWAP_WORDS 1
  28 +#endif
  29 +
  30 +#define FN_2(x) FN(x + 1) FN(x)
  31 +#define FN_4(x) FN_2(x + 2) FN_2(x)
  32 +
  33 +static void glue(pxa2xx_draw_line2_, BITS)(uint32_t *palette,
  34 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  35 +{
  36 + uint32_t data;
  37 + while (width > 0) {
  38 + data = *(uint32_t *) src;
  39 +#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
  40 +#ifdef SWAP_WORDS
  41 + FN_4(12)
  42 + FN_4(8)
  43 + FN_4(4)
  44 + FN_4(0)
  45 +#else
  46 + FN_4(0)
  47 + FN_4(4)
  48 + FN_4(8)
  49 + FN_4(12)
  50 +#endif
  51 +#undef FN
  52 + width -= 16;
  53 + src += 4;
  54 + }
  55 +}
  56 +
  57 +static void glue(pxa2xx_draw_line4_, BITS)(uint32_t *palette,
  58 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  59 +{
  60 + uint32_t data;
  61 + while (width > 0) {
  62 + data = *(uint32_t *) src;
  63 +#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
  64 +#ifdef SWAP_WORDS
  65 + FN_2(6)
  66 + FN_2(4)
  67 + FN_2(2)
  68 + FN_2(0)
  69 +#else
  70 + FN_2(0)
  71 + FN_2(2)
  72 + FN_2(4)
  73 + FN_2(6)
  74 +#endif
  75 +#undef FN
  76 + width -= 8;
  77 + src += 4;
  78 + }
  79 +}
  80 +
  81 +static void glue(pxa2xx_draw_line8_, BITS)(uint32_t *palette,
  82 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  83 +{
  84 + uint32_t data;
  85 + while (width > 0) {
  86 + data = *(uint32_t *) src;
  87 +#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
  88 +#ifdef SWAP_WORDS
  89 + FN(24)
  90 + FN(16)
  91 + FN(8)
  92 + FN(0)
  93 +#else
  94 + FN(0)
  95 + FN(8)
  96 + FN(16)
  97 + FN(24)
  98 +#endif
  99 +#undef FN
  100 + width -= 4;
  101 + src += 4;
  102 + }
  103 +}
  104 +
  105 +static void glue(pxa2xx_draw_line16_, BITS)(uint32_t *palette,
  106 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  107 +{
  108 + uint32_t data;
  109 + unsigned int r, g, b;
  110 + while (width > 0) {
  111 + data = *(uint32_t *) src;
  112 +#ifdef SWAP_WORDS
  113 + data = bswap32(data);
  114 +#endif
  115 + b = (data & 0x1f) << 3;
  116 + data >>= 5;
  117 + g = (data & 0x3f) << 2;
  118 + data >>= 6;
  119 + r = (data & 0x1f) << 3;
  120 + data >>= 5;
  121 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  122 + b = (data & 0x1f) << 3;
  123 + data >>= 5;
  124 + g = (data & 0x3f) << 2;
  125 + data >>= 6;
  126 + r = (data & 0x1f) << 3;
  127 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  128 + width -= 2;
  129 + src += 4;
  130 + }
  131 +}
  132 +
  133 +static void glue(pxa2xx_draw_line16t_, BITS)(uint32_t *palette,
  134 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  135 +{
  136 + uint32_t data;
  137 + unsigned int r, g, b;
  138 + while (width > 0) {
  139 + data = *(uint32_t *) src;
  140 +#ifdef SWAP_WORDS
  141 + data = bswap32(data);
  142 +#endif
  143 + b = (data & 0x1f) << 3;
  144 + data >>= 5;
  145 + g = (data & 0x1f) << 3;
  146 + data >>= 5;
  147 + r = (data & 0x1f) << 3;
  148 + data >>= 5;
  149 + if (data & 1)
  150 + SKIP_PIXEL(dest);
  151 + else
  152 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  153 + data >>= 1;
  154 + b = (data & 0x1f) << 3;
  155 + data >>= 5;
  156 + g = (data & 0x1f) << 3;
  157 + data >>= 5;
  158 + r = (data & 0x1f) << 3;
  159 + if (data & 1)
  160 + SKIP_PIXEL(dest);
  161 + else
  162 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  163 + width -= 2;
  164 + src += 4;
  165 + }
  166 +}
  167 +
  168 +static void glue(pxa2xx_draw_line18_, BITS)(uint32_t *palette,
  169 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  170 +{
  171 + uint32_t data;
  172 + unsigned int r, g, b;
  173 + while (width > 0) {
  174 + data = *(uint32_t *) src;
  175 +#ifdef SWAP_WORDS
  176 + data = bswap32(data);
  177 +#endif
  178 + b = (data & 0x3f) << 2;
  179 + data >>= 6;
  180 + g = (data & 0x3f) << 2;
  181 + data >>= 6;
  182 + r = (data & 0x3f) << 2;
  183 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  184 + width -= 1;
  185 + src += 4;
  186 + }
  187 +}
  188 +
  189 +/* The wicked packed format */
  190 +static void glue(pxa2xx_draw_line18p_, BITS)(uint32_t *palette,
  191 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  192 +{
  193 + uint32_t data[3];
  194 + unsigned int r, g, b;
  195 + while (width > 0) {
  196 + data[0] = *(uint32_t *) src;
  197 + src += 4;
  198 + data[1] = *(uint32_t *) src;
  199 + src += 4;
  200 + data[2] = *(uint32_t *) src;
  201 + src += 4;
  202 +#ifdef SWAP_WORDS
  203 + data[0] = bswap32(data[0]);
  204 + data[1] = bswap32(data[1]);
  205 + data[2] = bswap32(data[2]);
  206 +#endif
  207 + b = (data[0] & 0x3f) << 2;
  208 + data[0] >>= 6;
  209 + g = (data[0] & 0x3f) << 2;
  210 + data[0] >>= 6;
  211 + r = (data[0] & 0x3f) << 2;
  212 + data[0] >>= 12;
  213 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  214 + b = (data[0] & 0x3f) << 2;
  215 + data[0] >>= 6;
  216 + g = ((data[1] & 0xf) << 4) | (data[0] << 2);
  217 + data[1] >>= 4;
  218 + r = (data[1] & 0x3f) << 2;
  219 + data[1] >>= 12;
  220 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  221 + b = (data[1] & 0x3f) << 2;
  222 + data[1] >>= 6;
  223 + g = (data[1] & 0x3f) << 2;
  224 + data[1] >>= 6;
  225 + r = ((data[2] & 0x3) << 6) | (data[1] << 2);
  226 + data[2] >>= 8;
  227 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  228 + b = (data[2] & 0x3f) << 2;
  229 + data[2] >>= 6;
  230 + g = (data[2] & 0x3f) << 2;
  231 + data[2] >>= 6;
  232 + r = data[2] << 2;
  233 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  234 + width -= 4;
  235 + }
  236 +}
  237 +
  238 +static void glue(pxa2xx_draw_line19_, BITS)(uint32_t *palette,
  239 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  240 +{
  241 + uint32_t data;
  242 + unsigned int r, g, b;
  243 + while (width > 0) {
  244 + data = *(uint32_t *) src;
  245 +#ifdef SWAP_WORDS
  246 + data = bswap32(data);
  247 +#endif
  248 + b = (data & 0x3f) << 2;
  249 + data >>= 6;
  250 + g = (data & 0x3f) << 2;
  251 + data >>= 6;
  252 + r = (data & 0x3f) << 2;
  253 + data >>= 6;
  254 + if (data & 1)
  255 + SKIP_PIXEL(dest);
  256 + else
  257 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  258 + width -= 1;
  259 + src += 4;
  260 + }
  261 +}
  262 +
  263 +/* The wicked packed format */
  264 +static void glue(pxa2xx_draw_line19p_, BITS)(uint32_t *palette,
  265 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  266 +{
  267 + uint32_t data[3];
  268 + unsigned int r, g, b;
  269 + while (width > 0) {
  270 + data[0] = *(uint32_t *) src;
  271 + src += 4;
  272 + data[1] = *(uint32_t *) src;
  273 + src += 4;
  274 + data[2] = *(uint32_t *) src;
  275 + src += 4;
  276 +# ifdef SWAP_WORDS
  277 + data[0] = bswap32(data[0]);
  278 + data[1] = bswap32(data[1]);
  279 + data[2] = bswap32(data[2]);
  280 +# endif
  281 + b = (data[0] & 0x3f) << 2;
  282 + data[0] >>= 6;
  283 + g = (data[0] & 0x3f) << 2;
  284 + data[0] >>= 6;
  285 + r = (data[0] & 0x3f) << 2;
  286 + data[0] >>= 6;
  287 + if (data[0] & 1)
  288 + SKIP_PIXEL(dest);
  289 + else
  290 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  291 + data[0] >>= 6;
  292 + b = (data[0] & 0x3f) << 2;
  293 + data[0] >>= 6;
  294 + g = ((data[1] & 0xf) << 4) | (data[0] << 2);
  295 + data[1] >>= 4;
  296 + r = (data[1] & 0x3f) << 2;
  297 + data[1] >>= 6;
  298 + if (data[1] & 1)
  299 + SKIP_PIXEL(dest);
  300 + else
  301 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  302 + data[1] >>= 6;
  303 + b = (data[1] & 0x3f) << 2;
  304 + data[1] >>= 6;
  305 + g = (data[1] & 0x3f) << 2;
  306 + data[1] >>= 6;
  307 + r = ((data[2] & 0x3) << 6) | (data[1] << 2);
  308 + data[2] >>= 2;
  309 + if (data[2] & 1)
  310 + SKIP_PIXEL(dest);
  311 + else
  312 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  313 + data[2] >>= 6;
  314 + b = (data[2] & 0x3f) << 2;
  315 + data[2] >>= 6;
  316 + g = (data[2] & 0x3f) << 2;
  317 + data[2] >>= 6;
  318 + r = data[2] << 2;
  319 + data[2] >>= 6;
  320 + if (data[2] & 1)
  321 + SKIP_PIXEL(dest);
  322 + else
  323 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  324 + width -= 4;
  325 + }
  326 +}
  327 +
  328 +static void glue(pxa2xx_draw_line24_, BITS)(uint32_t *palette,
  329 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  330 +{
  331 + uint32_t data;
  332 + unsigned int r, g, b;
  333 + while (width > 0) {
  334 + data = *(uint32_t *) src;
  335 +#ifdef SWAP_WORDS
  336 + data = bswap32(data);
  337 +#endif
  338 + b = data & 0xff;
  339 + data >>= 8;
  340 + g = data & 0xff;
  341 + data >>= 8;
  342 + r = data & 0xff;
  343 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  344 + width -= 1;
  345 + src += 4;
  346 + }
  347 +}
  348 +
  349 +static void glue(pxa2xx_draw_line24t_, BITS)(uint32_t *palette,
  350 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  351 +{
  352 + uint32_t data;
  353 + unsigned int r, g, b;
  354 + while (width > 0) {
  355 + data = *(uint32_t *) src;
  356 +#ifdef SWAP_WORDS
  357 + data = bswap32(data);
  358 +#endif
  359 + b = (data & 0x7f) << 1;
  360 + data >>= 7;
  361 + g = data & 0xff;
  362 + data >>= 8;
  363 + r = data & 0xff;
  364 + data >>= 8;
  365 + if (data & 1)
  366 + SKIP_PIXEL(dest);
  367 + else
  368 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  369 + width -= 1;
  370 + src += 4;
  371 + }
  372 +}
  373 +
  374 +static void glue(pxa2xx_draw_line25_, BITS)(uint32_t *palette,
  375 + uint8_t *dest, const uint8_t *src, int width, int deststep)
  376 +{
  377 + uint32_t data;
  378 + unsigned int r, g, b;
  379 + while (width > 0) {
  380 + data = *(uint32_t *) src;
  381 +#ifdef SWAP_WORDS
  382 + data = bswap32(data);
  383 +#endif
  384 + b = data & 0xff;
  385 + data >>= 8;
  386 + g = data & 0xff;
  387 + data >>= 8;
  388 + r = data & 0xff;
  389 + data >>= 8;
  390 + if (data & 1)
  391 + SKIP_PIXEL(dest);
  392 + else
  393 + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
  394 + width -= 1;
  395 + src += 4;
  396 + }
  397 +}
  398 +
  399 +/* Overlay planes disabled, no transparency */
  400 +static drawfn glue(pxa2xx_draw_fn_, BITS)[16] =
  401 +{
  402 + [0 ... 0xf] = 0,
  403 + [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS),
  404 + [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
  405 + [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
  406 + [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS),
  407 + [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS),
  408 + [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS),
  409 + [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS),
  410 +};
  411 +
  412 +/* Overlay planes enabled, transparency used */
  413 +static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] =
  414 +{
  415 + [0 ... 0xf] = 0,
  416 + [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
  417 + [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
  418 + [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS),
  419 + [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS),
  420 + [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS),
  421 + [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS),
  422 + [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS),
  423 +};
  424 +
  425 +#undef BITS
  426 +#undef COPY_PIXEL
  427 +#undef SKIP_PIXEL
  428 +
  429 +#ifdef SWAP_WORDS
  430 +# undef SWAP_WORDS
  431 +#endif
... ...
hw/pxa2xx_timer.c 0 โ†’ 100644
  1 +/*
  2 + * Intel XScale PXA255/270 OS Timers.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Copyright (c) 2006 Thorsten Zitterell
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +#define OSMR0 0x00
  13 +#define OSMR1 0x04
  14 +#define OSMR2 0x08
  15 +#define OSMR3 0x0c
  16 +#define OSMR4 0x80
  17 +#define OSMR5 0x84
  18 +#define OSMR6 0x88
  19 +#define OSMR7 0x8c
  20 +#define OSMR8 0x90
  21 +#define OSMR9 0x94
  22 +#define OSMR10 0x98
  23 +#define OSMR11 0x9c
  24 +#define OSCR 0x10 /* OS Timer Count */
  25 +#define OSCR4 0x40
  26 +#define OSCR5 0x44
  27 +#define OSCR6 0x48
  28 +#define OSCR7 0x4c
  29 +#define OSCR8 0x50
  30 +#define OSCR9 0x54
  31 +#define OSCR10 0x58
  32 +#define OSCR11 0x5c
  33 +#define OSSR 0x14 /* Timer status register */
  34 +#define OWER 0x18
  35 +#define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
  36 +#define OMCR4 0xc0 /* OS Match Control registers */
  37 +#define OMCR5 0xc4
  38 +#define OMCR6 0xc8
  39 +#define OMCR7 0xcc
  40 +#define OMCR8 0xd0
  41 +#define OMCR9 0xd4
  42 +#define OMCR10 0xd8
  43 +#define OMCR11 0xdc
  44 +#define OSNR 0x20
  45 +
  46 +#define PXA25X_FREQ 3686400 /* 3.6864 MHz */
  47 +#define PXA27X_FREQ 3250000 /* 3.25 MHz */
  48 +
  49 +static int pxa2xx_timer4_freq[8] = {
  50 + [0] = 0,
  51 + [1] = 32768,
  52 + [2] = 1000,
  53 + [3] = 1,
  54 + [4] = 1000000,
  55 + /* [5] is the "Externally supplied clock". Assign if necessary. */
  56 + [5 ... 7] = 0,
  57 +};
  58 +
  59 +struct pxa2xx_timer0_s {
  60 + uint32_t value;
  61 + int level;
  62 + qemu_irq irq;
  63 + QEMUTimer *qtimer;
  64 + int num;
  65 + void *info;
  66 +};
  67 +
  68 +struct pxa2xx_timer4_s {
  69 + uint32_t value;
  70 + int level;
  71 + qemu_irq irq;
  72 + QEMUTimer *qtimer;
  73 + int num;
  74 + void *info;
  75 + int32_t oldclock;
  76 + int32_t clock;
  77 + uint64_t lastload;
  78 + uint32_t freq;
  79 + uint32_t control;
  80 +};
  81 +
  82 +typedef struct {
  83 + uint32_t base;
  84 + int32_t clock;
  85 + int32_t oldclock;
  86 + uint64_t lastload;
  87 + uint32_t freq;
  88 + struct pxa2xx_timer0_s timer[4];
  89 + struct pxa2xx_timer4_s *tm4;
  90 + uint32_t events;
  91 + uint32_t irq_enabled;
  92 + uint32_t reset3;
  93 + CPUState *cpustate;
  94 + int64_t qemu_ticks;
  95 + uint32_t snapshot;
  96 +} pxa2xx_timer_info;
  97 +
  98 +static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
  99 +{
  100 + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
  101 + int i;
  102 + uint32_t now_vm;
  103 + uint64_t new_qemu;
  104 +
  105 + now_vm = s->clock +
  106 + muldiv64(now_qemu - s->lastload, s->freq, ticks_per_sec);
  107 +
  108 + for (i = 0; i < 4; i ++) {
  109 + new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
  110 + ticks_per_sec, s->freq);
  111 + qemu_mod_timer(s->timer[i].qtimer, new_qemu);
  112 + }
  113 +}
  114 +
  115 +static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
  116 +{
  117 + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
  118 + uint32_t now_vm;
  119 + uint64_t new_qemu;
  120 + static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
  121 + int counter;
  122 +
  123 + if (s->tm4[n].control & (1 << 7))
  124 + counter = n;
  125 + else
  126 + counter = counters[n];
  127 +
  128 + if (!s->tm4[counter].freq) {
  129 + qemu_del_timer(s->timer[n].qtimer);
  130 + return;
  131 + }
  132 +
  133 + now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
  134 + s->tm4[counter].lastload,
  135 + s->tm4[counter].freq, ticks_per_sec);
  136 +
  137 + new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].value - now_vm),
  138 + ticks_per_sec, s->tm4[counter].freq);
  139 + qemu_mod_timer(s->timer[n].qtimer, new_qemu);
  140 +}
  141 +
  142 +static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
  143 +{
  144 + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
  145 + int tm = 0;
  146 +
  147 + offset -= s->base;
  148 +
  149 + switch (offset) {
  150 + case OSMR3: tm ++;
  151 + case OSMR2: tm ++;
  152 + case OSMR1: tm ++;
  153 + case OSMR0:
  154 + return s->timer[tm].value;
  155 + case OSMR11: tm ++;
  156 + case OSMR10: tm ++;
  157 + case OSMR9: tm ++;
  158 + case OSMR8: tm ++;
  159 + case OSMR7: tm ++;
  160 + case OSMR6: tm ++;
  161 + case OSMR5: tm ++;
  162 + case OSMR4:
  163 + if (!s->tm4)
  164 + goto badreg;
  165 + return s->tm4[tm].value;
  166 + case OSCR:
  167 + return s->clock + muldiv64(qemu_get_clock(vm_clock) -
  168 + s->lastload, s->freq, ticks_per_sec);
  169 + case OSCR11: tm ++;
  170 + case OSCR10: tm ++;
  171 + case OSCR9: tm ++;
  172 + case OSCR8: tm ++;
  173 + case OSCR7: tm ++;
  174 + case OSCR6: tm ++;
  175 + case OSCR5: tm ++;
  176 + case OSCR4:
  177 + if (!s->tm4)
  178 + goto badreg;
  179 +
  180 + if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
  181 + if (s->tm4[tm - 1].freq)
  182 + s->snapshot = s->tm4[tm - 1].clock + muldiv64(
  183 + qemu_get_clock(vm_clock) -
  184 + s->tm4[tm - 1].lastload,
  185 + s->tm4[tm - 1].freq, ticks_per_sec);
  186 + else
  187 + s->snapshot = s->tm4[tm - 1].clock;
  188 + }
  189 +
  190 + if (!s->tm4[tm].freq)
  191 + return s->tm4[tm].clock;
  192 + return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
  193 + s->tm4[tm].lastload, s->tm4[tm].freq, ticks_per_sec);
  194 + case OIER:
  195 + return s->irq_enabled;
  196 + case OSSR: /* Status register */
  197 + return s->events;
  198 + case OWER:
  199 + return s->reset3;
  200 + case OMCR11: tm ++;
  201 + case OMCR10: tm ++;
  202 + case OMCR9: tm ++;
  203 + case OMCR8: tm ++;
  204 + case OMCR7: tm ++;
  205 + case OMCR6: tm ++;
  206 + case OMCR5: tm ++;
  207 + case OMCR4:
  208 + if (!s->tm4)
  209 + goto badreg;
  210 + return s->tm4[tm].control;
  211 + case OSNR:
  212 + return s->snapshot;
  213 + default:
  214 + badreg:
  215 + cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
  216 + REG_FMT "\n", offset);
  217 + }
  218 +
  219 + return 0;
  220 +}
  221 +
  222 +static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
  223 + uint32_t value)
  224 +{
  225 + int i, tm = 0;
  226 + pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
  227 +
  228 + offset -= s->base;
  229 +
  230 + switch (offset) {
  231 + case OSMR3: tm ++;
  232 + case OSMR2: tm ++;
  233 + case OSMR1: tm ++;
  234 + case OSMR0:
  235 + s->timer[tm].value = value;
  236 + pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
  237 + break;
  238 + case OSMR11: tm ++;
  239 + case OSMR10: tm ++;
  240 + case OSMR9: tm ++;
  241 + case OSMR8: tm ++;
  242 + case OSMR7: tm ++;
  243 + case OSMR6: tm ++;
  244 + case OSMR5: tm ++;
  245 + case OSMR4:
  246 + if (!s->tm4)
  247 + goto badreg;
  248 + s->tm4[tm].value = value;
  249 + pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
  250 + break;
  251 + case OSCR:
  252 + s->oldclock = s->clock;
  253 + s->lastload = qemu_get_clock(vm_clock);
  254 + s->clock = value;
  255 + pxa2xx_timer_update(s, s->lastload);
  256 + break;
  257 + case OSCR11: tm ++;
  258 + case OSCR10: tm ++;
  259 + case OSCR9: tm ++;
  260 + case OSCR8: tm ++;
  261 + case OSCR7: tm ++;
  262 + case OSCR6: tm ++;
  263 + case OSCR5: tm ++;
  264 + case OSCR4:
  265 + if (!s->tm4)
  266 + goto badreg;
  267 + s->tm4[tm].oldclock = s->tm4[tm].clock;
  268 + s->tm4[tm].lastload = qemu_get_clock(vm_clock);
  269 + s->tm4[tm].clock = value;
  270 + pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
  271 + break;
  272 + case OIER:
  273 + s->irq_enabled = value & 0xfff;
  274 + break;
  275 + case OSSR: /* Status register */
  276 + s->events &= ~value;
  277 + for (i = 0; i < 4; i ++, value >>= 1) {
  278 + if (s->timer[i].level && (value & 1)) {
  279 + s->timer[i].level = 0;
  280 + qemu_irq_lower(s->timer[i].irq);
  281 + }
  282 + }
  283 + if (s->tm4) {
  284 + for (i = 0; i < 8; i ++, value >>= 1)
  285 + if (s->tm4[i].level && (value & 1))
  286 + s->tm4[i].level = 0;
  287 + if (!(s->events & 0xff0))
  288 + qemu_irq_lower(s->tm4->irq);
  289 + }
  290 + break;
  291 + case OWER: /* XXX: Reset on OSMR3 match? */
  292 + s->reset3 = value;
  293 + break;
  294 + case OMCR7: tm ++;
  295 + case OMCR6: tm ++;
  296 + case OMCR5: tm ++;
  297 + case OMCR4:
  298 + if (!s->tm4)
  299 + goto badreg;
  300 + s->tm4[tm].control = value & 0x0ff;
  301 + /* XXX Stop if running (shouldn't happen) */
  302 + if ((value & (1 << 7)) || tm == 0)
  303 + s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
  304 + else {
  305 + s->tm4[tm].freq = 0;
  306 + pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
  307 + }
  308 + break;
  309 + case OMCR11: tm ++;
  310 + case OMCR10: tm ++;
  311 + case OMCR9: tm ++;
  312 + case OMCR8: tm += 4;
  313 + if (!s->tm4)
  314 + goto badreg;
  315 + s->tm4[tm].control = value & 0x3ff;
  316 + /* XXX Stop if running (shouldn't happen) */
  317 + if ((value & (1 << 7)) || !(tm & 1))
  318 + s->tm4[tm].freq =
  319 + pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)];
  320 + else {
  321 + s->tm4[tm].freq = 0;
  322 + pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
  323 + }
  324 + break;
  325 + default:
  326 + badreg:
  327 + cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset "
  328 + REG_FMT "\n", offset);
  329 + }
  330 +}
  331 +
  332 +static CPUReadMemoryFunc *pxa2xx_timer_readfn[] = {
  333 + pxa2xx_timer_read,
  334 + pxa2xx_timer_read,
  335 + pxa2xx_timer_read,
  336 +};
  337 +
  338 +static CPUWriteMemoryFunc *pxa2xx_timer_writefn[] = {
  339 + pxa2xx_timer_write,
  340 + pxa2xx_timer_write,
  341 + pxa2xx_timer_write,
  342 +};
  343 +
  344 +static void pxa2xx_timer_tick(void *opaque)
  345 +{
  346 + struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
  347 + pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
  348 +
  349 + if (i->irq_enabled & (1 << t->num)) {
  350 + t->level = 1;
  351 + i->events |= 1 << t->num;
  352 + qemu_irq_raise(t->irq);
  353 + }
  354 +
  355 + if (t->num == 3)
  356 + if (i->reset3 & 1) {
  357 + i->reset3 = 0;
  358 + cpu_reset(i->cpustate);
  359 + }
  360 +}
  361 +
  362 +static void pxa2xx_timer_tick4(void *opaque)
  363 +{
  364 + struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
  365 + pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
  366 +
  367 + pxa2xx_timer_tick4(opaque);
  368 + if (t->control & (1 << 3))
  369 + t->clock = 0;
  370 + if (t->control & (1 << 6))
  371 + pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->num - 4);
  372 +}
  373 +
  374 +static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
  375 + qemu_irq *irqs, CPUState *cpustate)
  376 +{
  377 + int i;
  378 + int iomemtype;
  379 + pxa2xx_timer_info *s;
  380 +
  381 + s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
  382 + s->base = base;
  383 + s->irq_enabled = 0;
  384 + s->oldclock = 0;
  385 + s->clock = 0;
  386 + s->lastload = qemu_get_clock(vm_clock);
  387 + s->reset3 = 0;
  388 + s->cpustate = cpustate;
  389 +
  390 + for (i = 0; i < 4; i ++) {
  391 + s->timer[i].value = 0;
  392 + s->timer[i].irq = irqs[i];
  393 + s->timer[i].info = s;
  394 + s->timer[i].num = i;
  395 + s->timer[i].level = 0;
  396 + s->timer[i].qtimer = qemu_new_timer(vm_clock,
  397 + pxa2xx_timer_tick, &s->timer[i]);
  398 + }
  399 +
  400 + iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
  401 + pxa2xx_timer_writefn, s);
  402 + cpu_register_physical_memory(base, 0x00000fff, iomemtype);
  403 + return s;
  404 +}
  405 +
  406 +void pxa25x_timer_init(target_phys_addr_t base,
  407 + qemu_irq *irqs, CPUState *cpustate)
  408 +{
  409 + pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
  410 + s->freq = PXA25X_FREQ;
  411 + s->tm4 = 0;
  412 +}
  413 +
  414 +void pxa27x_timer_init(target_phys_addr_t base,
  415 + qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate)
  416 +{
  417 + pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
  418 + int i;
  419 + s->freq = PXA27X_FREQ;
  420 + s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
  421 + sizeof(struct pxa2xx_timer4_s));
  422 + for (i = 0; i < 8; i ++) {
  423 + s->tm4[i].value = 0;
  424 + s->tm4[i].irq = irq4;
  425 + s->tm4[i].info = s;
  426 + s->tm4[i].num = i + 4;
  427 + s->tm4[i].level = 0;
  428 + s->tm4[i].freq = 0;
  429 + s->tm4[i].control = 0x0;
  430 + s->tm4[i].qtimer = qemu_new_timer(vm_clock,
  431 + pxa2xx_timer_tick4, &s->tm4[i]);
  432 + }
  433 +}
... ...
... ... @@ -188,6 +188,7 @@ const char *vnc_display;
188 188 int acpi_enabled = 1;
189 189 int fd_bootchk = 1;
190 190 int no_reboot = 0;
  191 +int graphic_rotate = 0;
191 192 int daemonize = 0;
192 193 const char *option_rom[MAX_OPTION_ROMS];
193 194 int nb_option_roms;
... ... @@ -524,6 +525,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
524 525 {
525 526 QEMUPutMouseEvent *mouse_event;
526 527 void *mouse_event_opaque;
  528 + int width;
527 529  
528 530 if (!qemu_put_mouse_event_current) {
529 531 return;
... ... @@ -535,7 +537,16 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
535 537 qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
536 538  
537 539 if (mouse_event) {
538   - mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
  540 + if (graphic_rotate) {
  541 + if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
  542 + width = 0x7fff;
  543 + else
  544 + width = graphic_width;
  545 + mouse_event(mouse_event_opaque,
  546 + width - dy, dx, dz, buttons_state);
  547 + } else
  548 + mouse_event(mouse_event_opaque,
  549 + dx, dy, dz, buttons_state);
539 550 }
540 551 }
541 552  
... ... @@ -6422,6 +6433,7 @@ void help(void)
6422 6433 "-m megs set virtual RAM size to megs MB [default=%d]\n"
6423 6434 "-smp n set the number of CPUs to 'n' [default=1]\n"
6424 6435 "-nographic disable graphical output and redirect serial I/Os to console\n"
  6436 + "-portrait rotate graphical output 90 deg left (only PXA LCD)\n"
6425 6437 #ifndef _WIN32
6426 6438 "-k language use keyboard layout (for example \"fr\" for French)\n"
6427 6439 #endif
... ... @@ -6556,6 +6568,7 @@ enum {
6556 6568 #endif
6557 6569 QEMU_OPTION_m,
6558 6570 QEMU_OPTION_nographic,
  6571 + QEMU_OPTION_portrait,
6559 6572 #ifdef HAS_AUDIO
6560 6573 QEMU_OPTION_audio_help,
6561 6574 QEMU_OPTION_soundhw,
... ... @@ -6636,6 +6649,7 @@ const QEMUOption qemu_options[] = {
6636 6649 #endif
6637 6650 { "m", HAS_ARG, QEMU_OPTION_m },
6638 6651 { "nographic", 0, QEMU_OPTION_nographic },
  6652 + { "portrait", 0, QEMU_OPTION_portrait },
6639 6653 { "k", HAS_ARG, QEMU_OPTION_k },
6640 6654 #ifdef HAS_AUDIO
6641 6655 { "audio-help", 0, QEMU_OPTION_audio_help },
... ... @@ -7167,6 +7181,9 @@ int main(int argc, char **argv)
7167 7181 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
7168 7182 nographic = 1;
7169 7183 break;
  7184 + case QEMU_OPTION_portrait:
  7185 + graphic_rotate = 1;
  7186 + break;
7170 7187 case QEMU_OPTION_kernel:
7171 7188 kernel_filename = optarg;
7172 7189 break;
... ... @@ -7658,7 +7675,7 @@ int main(int argc, char **argv)
7658 7675 fprintf(stderr, "qemu: could not open SD card image %s\n",
7659 7676 sd_filename);
7660 7677 } else
7661   - qemu_key_check(bs, sd_filename);
  7678 + qemu_key_check(sd_bdrv, sd_filename);
7662 7679 }
7663 7680  
7664 7681 register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
... ...
... ... @@ -158,6 +158,7 @@ extern int kqemu_allowed;
158 158 extern int win2k_install_hack;
159 159 extern int usb_enabled;
160 160 extern int smp_cpus;
  161 +extern int graphic_rotate;
161 162 extern int no_quit;
162 163 extern int semihosting_enabled;
163 164 extern int autostart;
... ...