symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/musicpal.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Marvell MV88W8618 / Freecom MusicPal emulation.
       
     3  *
       
     4  * Copyright (c) 2008 Jan Kiszka
       
     5  *
       
     6  * This code is licenced under the GNU GPL v2.
       
     7  */
       
     8 
       
     9 #include "hw.h"
       
    10 #include "arm-misc.h"
       
    11 #include "devices.h"
       
    12 #include "net.h"
       
    13 #include "sysemu.h"
       
    14 #include "boards.h"
       
    15 #include "pc.h"
       
    16 #include "qemu-timer.h"
       
    17 #include "block.h"
       
    18 #include "flash.h"
       
    19 #include "gui.h"
       
    20 #include "audio/audio.h"
       
    21 #include "i2c.h"
       
    22 
       
    23 #define MP_ETH_BASE             0x80008000
       
    24 #define MP_ETH_SIZE             0x00001000
       
    25 
       
    26 #define MP_UART1_BASE           0x8000C840
       
    27 #define MP_UART2_BASE           0x8000C940
       
    28 
       
    29 #define MP_FLASHCFG_BASE        0x90006000
       
    30 #define MP_FLASHCFG_SIZE        0x00001000
       
    31 
       
    32 #define MP_AUDIO_BASE           0x90007000
       
    33 #define MP_AUDIO_SIZE           0x00001000
       
    34 
       
    35 #define MP_PIC_BASE             0x90008000
       
    36 #define MP_PIC_SIZE             0x00001000
       
    37 
       
    38 #define MP_PIT_BASE             0x90009000
       
    39 #define MP_PIT_SIZE             0x00001000
       
    40 
       
    41 #define MP_LCD_BASE             0x9000c000
       
    42 #define MP_LCD_SIZE             0x00001000
       
    43 
       
    44 #define MP_SRAM_BASE            0xC0000000
       
    45 #define MP_SRAM_SIZE            0x00020000
       
    46 
       
    47 #define MP_RAM_DEFAULT_SIZE     32*1024*1024
       
    48 #define MP_FLASH_SIZE_MAX       32*1024*1024
       
    49 
       
    50 #define MP_TIMER1_IRQ           4
       
    51 /* ... */
       
    52 #define MP_TIMER4_IRQ           7
       
    53 #define MP_EHCI_IRQ             8
       
    54 #define MP_ETH_IRQ              9
       
    55 #define MP_UART1_IRQ            11
       
    56 #define MP_UART2_IRQ            11
       
    57 #define MP_GPIO_IRQ             12
       
    58 #define MP_RTC_IRQ              28
       
    59 #define MP_AUDIO_IRQ            30
       
    60 
       
    61 static uint32_t gpio_in_state = 0xffffffff;
       
    62 static uint32_t gpio_isr;
       
    63 static uint32_t gpio_out_state;
       
    64 static ram_addr_t sram_off;
       
    65 
       
    66 /* Address conversion helpers */
       
    67 static void *target2host_addr(uint32_t addr)
       
    68 {
       
    69     /* FIXME: This is broken if it spans multiple RAM regions.  */
       
    70     if (addr < MP_SRAM_BASE) {
       
    71         if (addr >= MP_RAM_DEFAULT_SIZE)
       
    72             return NULL;
       
    73         return host_ram_addr(addr);
       
    74     } else {
       
    75         if (addr >= MP_SRAM_BASE + MP_SRAM_SIZE)
       
    76             return NULL;
       
    77         return host_ram_addr(sram_off + addr - MP_SRAM_BASE);
       
    78     }
       
    79 }
       
    80 
       
    81 static uint32_t host2target_addr(void *addr)
       
    82 {
       
    83     /* FIXME: This is broken if it spans multiple RAM regions.  */
       
    84     ram_addr_t offset = ram_offset_from_host(addr);
       
    85     if (offset < sram_off)
       
    86         return offset;
       
    87     else
       
    88         return offset - sram_off + MP_SRAM_BASE;
       
    89 }
       
    90 
       
    91 
       
    92 typedef enum i2c_state {
       
    93     STOPPED = 0,
       
    94     INITIALIZING,
       
    95     SENDING_BIT7,
       
    96     SENDING_BIT6,
       
    97     SENDING_BIT5,
       
    98     SENDING_BIT4,
       
    99     SENDING_BIT3,
       
   100     SENDING_BIT2,
       
   101     SENDING_BIT1,
       
   102     SENDING_BIT0,
       
   103     WAITING_FOR_ACK,
       
   104     RECEIVING_BIT7,
       
   105     RECEIVING_BIT6,
       
   106     RECEIVING_BIT5,
       
   107     RECEIVING_BIT4,
       
   108     RECEIVING_BIT3,
       
   109     RECEIVING_BIT2,
       
   110     RECEIVING_BIT1,
       
   111     RECEIVING_BIT0,
       
   112     SENDING_ACK
       
   113 } i2c_state;
       
   114 
       
   115 typedef struct i2c_interface {
       
   116     i2c_bus *bus;
       
   117     i2c_state state;
       
   118     int last_data;
       
   119     int last_clock;
       
   120     uint8_t buffer;
       
   121     int current_addr;
       
   122 } i2c_interface;
       
   123 
       
   124 static void i2c_enter_stop(i2c_interface *i2c)
       
   125 {
       
   126     if (i2c->current_addr >= 0)
       
   127         i2c_end_transfer(i2c->bus);
       
   128     i2c->current_addr = -1;
       
   129     i2c->state = STOPPED;
       
   130 }
       
   131 
       
   132 static void i2c_state_update(i2c_interface *i2c, int data, int clock)
       
   133 {
       
   134     if (!i2c)
       
   135         return;
       
   136 
       
   137     switch (i2c->state) {
       
   138     case STOPPED:
       
   139         if (data == 0 && i2c->last_data == 1 && clock == 1)
       
   140             i2c->state = INITIALIZING;
       
   141         break;
       
   142 
       
   143     case INITIALIZING:
       
   144         if (clock == 0 && i2c->last_clock == 1 && data == 0)
       
   145             i2c->state = SENDING_BIT7;
       
   146         else
       
   147             i2c_enter_stop(i2c);
       
   148         break;
       
   149 
       
   150     case SENDING_BIT7 ... SENDING_BIT0:
       
   151         if (clock == 0 && i2c->last_clock == 1) {
       
   152             i2c->buffer = (i2c->buffer << 1) | data;
       
   153             i2c->state++; /* will end up in WAITING_FOR_ACK */
       
   154         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
       
   155             i2c_enter_stop(i2c);
       
   156         break;
       
   157 
       
   158     case WAITING_FOR_ACK:
       
   159         if (clock == 0 && i2c->last_clock == 1) {
       
   160             if (i2c->current_addr < 0) {
       
   161                 i2c->current_addr = i2c->buffer;
       
   162                 i2c_start_transfer(i2c->bus, i2c->current_addr & 0xfe,
       
   163                                    i2c->buffer & 1);
       
   164             } else
       
   165                 i2c_send(i2c->bus, i2c->buffer);
       
   166             if (i2c->current_addr & 1) {
       
   167                 i2c->state = RECEIVING_BIT7;
       
   168                 i2c->buffer = i2c_recv(i2c->bus);
       
   169             } else
       
   170                 i2c->state = SENDING_BIT7;
       
   171         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
       
   172             i2c_enter_stop(i2c);
       
   173         break;
       
   174 
       
   175     case RECEIVING_BIT7 ... RECEIVING_BIT0:
       
   176         if (clock == 0 && i2c->last_clock == 1) {
       
   177             i2c->state++; /* will end up in SENDING_ACK */
       
   178             i2c->buffer <<= 1;
       
   179         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
       
   180             i2c_enter_stop(i2c);
       
   181         break;
       
   182 
       
   183     case SENDING_ACK:
       
   184         if (clock == 0 && i2c->last_clock == 1) {
       
   185             i2c->state = RECEIVING_BIT7;
       
   186             if (data == 0)
       
   187                 i2c->buffer = i2c_recv(i2c->bus);
       
   188             else
       
   189                 i2c_nack(i2c->bus);
       
   190         } else if (data == 1 && i2c->last_data == 0 && clock == 1)
       
   191             i2c_enter_stop(i2c);
       
   192         break;
       
   193     }
       
   194 
       
   195     i2c->last_data = data;
       
   196     i2c->last_clock = clock;
       
   197 }
       
   198 
       
   199 static int i2c_get_data(i2c_interface *i2c)
       
   200 {
       
   201     if (!i2c)
       
   202         return 0;
       
   203 
       
   204     switch (i2c->state) {
       
   205     case RECEIVING_BIT7 ... RECEIVING_BIT0:
       
   206         return (i2c->buffer >> 7);
       
   207 
       
   208     case WAITING_FOR_ACK:
       
   209     default:
       
   210         return 0;
       
   211     }
       
   212 }
       
   213 
       
   214 static i2c_interface *mixer_i2c;
       
   215 
       
   216 #ifdef HAS_AUDIO
       
   217 
       
   218 /* Audio register offsets */
       
   219 #define MP_AUDIO_PLAYBACK_MODE  0x00
       
   220 #define MP_AUDIO_CLOCK_DIV      0x18
       
   221 #define MP_AUDIO_IRQ_STATUS     0x20
       
   222 #define MP_AUDIO_IRQ_ENABLE     0x24
       
   223 #define MP_AUDIO_TX_START_LO    0x28
       
   224 #define MP_AUDIO_TX_THRESHOLD   0x2C
       
   225 #define MP_AUDIO_TX_STATUS      0x38
       
   226 #define MP_AUDIO_TX_START_HI    0x40
       
   227 
       
   228 /* Status register and IRQ enable bits */
       
   229 #define MP_AUDIO_TX_HALF        (1 << 6)
       
   230 #define MP_AUDIO_TX_FULL        (1 << 7)
       
   231 
       
   232 /* Playback mode bits */
       
   233 #define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
       
   234 #define MP_AUDIO_PLAYBACK_EN    (1 << 7)
       
   235 #define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
       
   236 #define MP_AUDIO_MONO           (1 << 14)
       
   237 
       
   238 /* Wolfson 8750 I2C address */
       
   239 #define MP_WM_ADDR              0x34
       
   240 
       
   241 static const char audio_name[] = "mv88w8618";
       
   242 
       
   243 typedef struct musicpal_audio_state {
       
   244     qemu_irq irq;
       
   245     uint32_t playback_mode;
       
   246     uint32_t status;
       
   247     uint32_t irq_enable;
       
   248     unsigned long phys_buf;
       
   249     int8_t *target_buffer;
       
   250     unsigned int threshold;
       
   251     unsigned int play_pos;
       
   252     unsigned int last_free;
       
   253     uint32_t clock_div;
       
   254     i2c_slave *wm;
       
   255 } musicpal_audio_state;
       
   256 
       
   257 static void audio_callback(void *opaque, int free_out, int free_in)
       
   258 {
       
   259     musicpal_audio_state *s = opaque;
       
   260     int16_t *codec_buffer;
       
   261     int8_t *mem_buffer;
       
   262     int pos, block_size;
       
   263 
       
   264     if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN))
       
   265         return;
       
   266 
       
   267     if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
       
   268         free_out <<= 1;
       
   269 
       
   270     if (!(s->playback_mode & MP_AUDIO_MONO))
       
   271         free_out <<= 1;
       
   272 
       
   273     block_size = s->threshold/2;
       
   274     if (free_out - s->last_free < block_size)
       
   275         return;
       
   276 
       
   277     mem_buffer = s->target_buffer + s->play_pos;
       
   278     if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
       
   279         if (s->playback_mode & MP_AUDIO_MONO) {
       
   280             codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
       
   281             for (pos = 0; pos < block_size; pos += 2) {
       
   282                 *codec_buffer++ = *(int16_t *)mem_buffer;
       
   283                 *codec_buffer++ = *(int16_t *)mem_buffer;
       
   284                 mem_buffer += 2;
       
   285             }
       
   286         } else
       
   287             memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
       
   288                    (uint32_t *)mem_buffer, block_size);
       
   289     } else {
       
   290         if (s->playback_mode & MP_AUDIO_MONO) {
       
   291             codec_buffer = wm8750_dac_buffer(s->wm, block_size);
       
   292             for (pos = 0; pos < block_size; pos++) {
       
   293                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
       
   294                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
       
   295             }
       
   296         } else {
       
   297             codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
       
   298             for (pos = 0; pos < block_size; pos += 2) {
       
   299                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
       
   300                 *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
       
   301             }
       
   302         }
       
   303     }
       
   304     wm8750_dac_commit(s->wm);
       
   305 
       
   306     s->last_free = free_out - block_size;
       
   307 
       
   308     if (s->play_pos == 0) {
       
   309         s->status |= MP_AUDIO_TX_HALF;
       
   310         s->play_pos = block_size;
       
   311     } else {
       
   312         s->status |= MP_AUDIO_TX_FULL;
       
   313         s->play_pos = 0;
       
   314     }
       
   315 
       
   316     if (s->status & s->irq_enable)
       
   317         qemu_irq_raise(s->irq);
       
   318 }
       
   319 
       
   320 static void musicpal_audio_clock_update(musicpal_audio_state *s)
       
   321 {
       
   322     int rate;
       
   323 
       
   324     if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ)
       
   325         rate = 24576000 / 64; /* 24.576MHz */
       
   326     else
       
   327         rate = 11289600 / 64; /* 11.2896MHz */
       
   328 
       
   329     rate /= ((s->clock_div >> 8) & 0xff) + 1;
       
   330 
       
   331     wm8750_set_bclk_in(s->wm, rate);
       
   332 }
       
   333 
       
   334 static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset)
       
   335 {
       
   336     musicpal_audio_state *s = opaque;
       
   337 
       
   338     switch (offset) {
       
   339     case MP_AUDIO_PLAYBACK_MODE:
       
   340         return s->playback_mode;
       
   341 
       
   342     case MP_AUDIO_CLOCK_DIV:
       
   343         return s->clock_div;
       
   344 
       
   345     case MP_AUDIO_IRQ_STATUS:
       
   346         return s->status;
       
   347 
       
   348     case MP_AUDIO_IRQ_ENABLE:
       
   349         return s->irq_enable;
       
   350 
       
   351     case MP_AUDIO_TX_STATUS:
       
   352         return s->play_pos >> 2;
       
   353 
       
   354     default:
       
   355         return 0;
       
   356     }
       
   357 }
       
   358 
       
   359 static void musicpal_audio_write(void *opaque, target_phys_addr_t offset,
       
   360                                  uint32_t value)
       
   361 {
       
   362     musicpal_audio_state *s = opaque;
       
   363 
       
   364     switch (offset) {
       
   365     case MP_AUDIO_PLAYBACK_MODE:
       
   366         if (value & MP_AUDIO_PLAYBACK_EN &&
       
   367             !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
       
   368             s->status = 0;
       
   369             s->last_free = 0;
       
   370             s->play_pos = 0;
       
   371         }
       
   372         s->playback_mode = value;
       
   373         musicpal_audio_clock_update(s);
       
   374         break;
       
   375 
       
   376     case MP_AUDIO_CLOCK_DIV:
       
   377         s->clock_div = value;
       
   378         s->last_free = 0;
       
   379         s->play_pos = 0;
       
   380         musicpal_audio_clock_update(s);
       
   381         break;
       
   382 
       
   383     case MP_AUDIO_IRQ_STATUS:
       
   384         s->status &= ~value;
       
   385         break;
       
   386 
       
   387     case MP_AUDIO_IRQ_ENABLE:
       
   388         s->irq_enable = value;
       
   389         if (s->status & s->irq_enable)
       
   390             qemu_irq_raise(s->irq);
       
   391         break;
       
   392 
       
   393     case MP_AUDIO_TX_START_LO:
       
   394         s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
       
   395         s->target_buffer = target2host_addr(s->phys_buf);
       
   396         s->play_pos = 0;
       
   397         s->last_free = 0;
       
   398         break;
       
   399 
       
   400     case MP_AUDIO_TX_THRESHOLD:
       
   401         s->threshold = (value + 1) * 4;
       
   402         break;
       
   403 
       
   404     case MP_AUDIO_TX_START_HI:
       
   405         s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
       
   406         s->target_buffer = target2host_addr(s->phys_buf);
       
   407         s->play_pos = 0;
       
   408         s->last_free = 0;
       
   409         break;
       
   410     }
       
   411 }
       
   412 
       
   413 static void musicpal_audio_reset(void *opaque)
       
   414 {
       
   415     musicpal_audio_state *s = opaque;
       
   416 
       
   417     s->playback_mode = 0;
       
   418     s->status = 0;
       
   419     s->irq_enable = 0;
       
   420 }
       
   421 
       
   422 static CPUReadMemoryFunc *musicpal_audio_readfn[] = {
       
   423     musicpal_audio_read,
       
   424     musicpal_audio_read,
       
   425     musicpal_audio_read
       
   426 };
       
   427 
       
   428 static CPUWriteMemoryFunc *musicpal_audio_writefn[] = {
       
   429     musicpal_audio_write,
       
   430     musicpal_audio_write,
       
   431     musicpal_audio_write
       
   432 };
       
   433 
       
   434 static i2c_interface *musicpal_audio_init(uint32_t base, qemu_irq irq)
       
   435 {
       
   436     AudioState *audio;
       
   437     musicpal_audio_state *s;
       
   438     i2c_interface *i2c;
       
   439     int iomemtype;
       
   440 
       
   441     audio = AUD_init();
       
   442     if (!audio) {
       
   443         AUD_log(audio_name, "No audio state\n");
       
   444         return NULL;
       
   445     }
       
   446 
       
   447     s = qemu_mallocz(sizeof(musicpal_audio_state));
       
   448     if (!s)
       
   449         return NULL;
       
   450     s->irq = irq;
       
   451 
       
   452     i2c = qemu_mallocz(sizeof(i2c_interface));
       
   453     if (!i2c)
       
   454         return NULL;
       
   455     i2c->bus = i2c_init_bus();
       
   456     i2c->current_addr = -1;
       
   457 
       
   458     s->wm = wm8750_init(i2c->bus, audio);
       
   459     if (!s->wm)
       
   460         return NULL;
       
   461     i2c_set_slave_address(s->wm, MP_WM_ADDR);
       
   462     wm8750_data_req_set(s->wm, audio_callback, s);
       
   463 
       
   464     iomemtype = cpu_register_io_memory(0, musicpal_audio_readfn,
       
   465                        musicpal_audio_writefn, s);
       
   466     cpu_register_physical_memory(base, MP_AUDIO_SIZE, iomemtype);
       
   467 
       
   468     qemu_register_reset(musicpal_audio_reset, s);
       
   469 
       
   470     return i2c;
       
   471 }
       
   472 #else  /* !HAS_AUDIO */
       
   473 static i2c_interface *musicpal_audio_init(uint32_t base, qemu_irq irq)
       
   474 {
       
   475     return NULL;
       
   476 }
       
   477 #endif /* !HAS_AUDIO */
       
   478 
       
   479 /* Ethernet register offsets */
       
   480 #define MP_ETH_SMIR             0x010
       
   481 #define MP_ETH_PCXR             0x408
       
   482 #define MP_ETH_SDCMR            0x448
       
   483 #define MP_ETH_ICR              0x450
       
   484 #define MP_ETH_IMR              0x458
       
   485 #define MP_ETH_FRDP0            0x480
       
   486 #define MP_ETH_FRDP1            0x484
       
   487 #define MP_ETH_FRDP2            0x488
       
   488 #define MP_ETH_FRDP3            0x48C
       
   489 #define MP_ETH_CRDP0            0x4A0
       
   490 #define MP_ETH_CRDP1            0x4A4
       
   491 #define MP_ETH_CRDP2            0x4A8
       
   492 #define MP_ETH_CRDP3            0x4AC
       
   493 #define MP_ETH_CTDP0            0x4E0
       
   494 #define MP_ETH_CTDP1            0x4E4
       
   495 #define MP_ETH_CTDP2            0x4E8
       
   496 #define MP_ETH_CTDP3            0x4EC
       
   497 
       
   498 /* MII PHY access */
       
   499 #define MP_ETH_SMIR_DATA        0x0000FFFF
       
   500 #define MP_ETH_SMIR_ADDR        0x03FF0000
       
   501 #define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
       
   502 #define MP_ETH_SMIR_RDVALID     (1 << 27)
       
   503 
       
   504 /* PHY registers */
       
   505 #define MP_ETH_PHY1_BMSR        0x00210000
       
   506 #define MP_ETH_PHY1_PHYSID1     0x00410000
       
   507 #define MP_ETH_PHY1_PHYSID2     0x00610000
       
   508 
       
   509 #define MP_PHY_BMSR_LINK        0x0004
       
   510 #define MP_PHY_BMSR_AUTONEG     0x0008
       
   511 
       
   512 #define MP_PHY_88E3015          0x01410E20
       
   513 
       
   514 /* TX descriptor status */
       
   515 #define MP_ETH_TX_OWN           (1 << 31)
       
   516 
       
   517 /* RX descriptor status */
       
   518 #define MP_ETH_RX_OWN           (1 << 31)
       
   519 
       
   520 /* Interrupt cause/mask bits */
       
   521 #define MP_ETH_IRQ_RX_BIT       0
       
   522 #define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
       
   523 #define MP_ETH_IRQ_TXHI_BIT     2
       
   524 #define MP_ETH_IRQ_TXLO_BIT     3
       
   525 
       
   526 /* Port config bits */
       
   527 #define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
       
   528 
       
   529 /* SDMA command bits */
       
   530 #define MP_ETH_CMD_TXHI         (1 << 23)
       
   531 #define MP_ETH_CMD_TXLO         (1 << 22)
       
   532 
       
   533 typedef struct mv88w8618_tx_desc {
       
   534     uint32_t cmdstat;
       
   535     uint16_t res;
       
   536     uint16_t bytes;
       
   537     uint32_t buffer;
       
   538     uint32_t next;
       
   539 } mv88w8618_tx_desc;
       
   540 
       
   541 typedef struct mv88w8618_rx_desc {
       
   542     uint32_t cmdstat;
       
   543     uint16_t bytes;
       
   544     uint16_t buffer_size;
       
   545     uint32_t buffer;
       
   546     uint32_t next;
       
   547 } mv88w8618_rx_desc;
       
   548 
       
   549 typedef struct mv88w8618_eth_state {
       
   550     qemu_irq irq;
       
   551     uint32_t smir;
       
   552     uint32_t icr;
       
   553     uint32_t imr;
       
   554     int vlan_header;
       
   555     mv88w8618_tx_desc *tx_queue[2];
       
   556     mv88w8618_rx_desc *rx_queue[4];
       
   557     mv88w8618_rx_desc *frx_queue[4];
       
   558     mv88w8618_rx_desc *cur_rx[4];
       
   559     VLANClientState *vc;
       
   560 } mv88w8618_eth_state;
       
   561 
       
   562 static int eth_can_receive(void *opaque)
       
   563 {
       
   564     return 1;
       
   565 }
       
   566 
       
   567 static void eth_receive(void *opaque, const uint8_t *buf, int size)
       
   568 {
       
   569     mv88w8618_eth_state *s = opaque;
       
   570     mv88w8618_rx_desc *desc;
       
   571     int i;
       
   572 
       
   573     for (i = 0; i < 4; i++) {
       
   574         desc = s->cur_rx[i];
       
   575         if (!desc)
       
   576             continue;
       
   577         do {
       
   578             if (le32_to_cpu(desc->cmdstat) & MP_ETH_RX_OWN &&
       
   579                 le16_to_cpu(desc->buffer_size) >= size) {
       
   580                 memcpy(target2host_addr(le32_to_cpu(desc->buffer) +
       
   581                                         s->vlan_header),
       
   582                        buf, size);
       
   583                 desc->bytes = cpu_to_le16(size + s->vlan_header);
       
   584                 desc->cmdstat &= cpu_to_le32(~MP_ETH_RX_OWN);
       
   585                 s->cur_rx[i] = target2host_addr(le32_to_cpu(desc->next));
       
   586 
       
   587                 s->icr |= MP_ETH_IRQ_RX;
       
   588                 if (s->icr & s->imr)
       
   589                     qemu_irq_raise(s->irq);
       
   590                 return;
       
   591             }
       
   592             desc = target2host_addr(le32_to_cpu(desc->next));
       
   593         } while (desc != s->rx_queue[i]);
       
   594     }
       
   595 }
       
   596 
       
   597 static void eth_send(mv88w8618_eth_state *s, int queue_index)
       
   598 {
       
   599     mv88w8618_tx_desc *desc = s->tx_queue[queue_index];
       
   600 
       
   601     do {
       
   602         if (le32_to_cpu(desc->cmdstat) & MP_ETH_TX_OWN) {
       
   603             qemu_send_packet(s->vc,
       
   604                              target2host_addr(le32_to_cpu(desc->buffer)),
       
   605                              le16_to_cpu(desc->bytes));
       
   606             desc->cmdstat &= cpu_to_le32(~MP_ETH_TX_OWN);
       
   607             s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
       
   608         }
       
   609         desc = target2host_addr(le32_to_cpu(desc->next));
       
   610     } while (desc != s->tx_queue[queue_index]);
       
   611 }
       
   612 
       
   613 static uint32_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset)
       
   614 {
       
   615     mv88w8618_eth_state *s = opaque;
       
   616 
       
   617     switch (offset) {
       
   618     case MP_ETH_SMIR:
       
   619         if (s->smir & MP_ETH_SMIR_OPCODE) {
       
   620             switch (s->smir & MP_ETH_SMIR_ADDR) {
       
   621             case MP_ETH_PHY1_BMSR:
       
   622                 return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
       
   623                        MP_ETH_SMIR_RDVALID;
       
   624             case MP_ETH_PHY1_PHYSID1:
       
   625                 return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
       
   626             case MP_ETH_PHY1_PHYSID2:
       
   627                 return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
       
   628             default:
       
   629                 return MP_ETH_SMIR_RDVALID;
       
   630             }
       
   631         }
       
   632         return 0;
       
   633 
       
   634     case MP_ETH_ICR:
       
   635         return s->icr;
       
   636 
       
   637     case MP_ETH_IMR:
       
   638         return s->imr;
       
   639 
       
   640     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
       
   641         return host2target_addr(s->frx_queue[(offset - MP_ETH_FRDP0)/4]);
       
   642 
       
   643     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
       
   644         return host2target_addr(s->rx_queue[(offset - MP_ETH_CRDP0)/4]);
       
   645 
       
   646     case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
       
   647         return host2target_addr(s->tx_queue[(offset - MP_ETH_CTDP0)/4]);
       
   648 
       
   649     default:
       
   650         return 0;
       
   651     }
       
   652 }
       
   653 
       
   654 static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,
       
   655                                 uint32_t value)
       
   656 {
       
   657     mv88w8618_eth_state *s = opaque;
       
   658 
       
   659     switch (offset) {
       
   660     case MP_ETH_SMIR:
       
   661         s->smir = value;
       
   662         break;
       
   663 
       
   664     case MP_ETH_PCXR:
       
   665         s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
       
   666         break;
       
   667 
       
   668     case MP_ETH_SDCMR:
       
   669         if (value & MP_ETH_CMD_TXHI)
       
   670             eth_send(s, 1);
       
   671         if (value & MP_ETH_CMD_TXLO)
       
   672             eth_send(s, 0);
       
   673         if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr)
       
   674             qemu_irq_raise(s->irq);
       
   675         break;
       
   676 
       
   677     case MP_ETH_ICR:
       
   678         s->icr &= value;
       
   679         break;
       
   680 
       
   681     case MP_ETH_IMR:
       
   682         s->imr = value;
       
   683         if (s->icr & s->imr)
       
   684             qemu_irq_raise(s->irq);
       
   685         break;
       
   686 
       
   687     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
       
   688         s->frx_queue[(offset - MP_ETH_FRDP0)/4] = target2host_addr(value);
       
   689         break;
       
   690 
       
   691     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
       
   692         s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
       
   693             s->cur_rx[(offset - MP_ETH_CRDP0)/4] = target2host_addr(value);
       
   694         break;
       
   695 
       
   696     case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
       
   697         s->tx_queue[(offset - MP_ETH_CTDP0)/4] = target2host_addr(value);
       
   698         break;
       
   699     }
       
   700 }
       
   701 
       
   702 static CPUReadMemoryFunc *mv88w8618_eth_readfn[] = {
       
   703     mv88w8618_eth_read,
       
   704     mv88w8618_eth_read,
       
   705     mv88w8618_eth_read
       
   706 };
       
   707 
       
   708 static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {
       
   709     mv88w8618_eth_write,
       
   710     mv88w8618_eth_write,
       
   711     mv88w8618_eth_write
       
   712 };
       
   713 
       
   714 static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
       
   715 {
       
   716     mv88w8618_eth_state *s;
       
   717     int iomemtype;
       
   718 
       
   719     s = qemu_mallocz(sizeof(mv88w8618_eth_state));
       
   720     if (!s)
       
   721         return;
       
   722     s->irq = irq;
       
   723     s->vc = qemu_new_vlan_client(nd->vlan, eth_receive, eth_can_receive, s);
       
   724     iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,
       
   725                                        mv88w8618_eth_writefn, s);
       
   726     cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);
       
   727 }
       
   728 
       
   729 /* LCD register offsets */
       
   730 #define MP_LCD_IRQCTRL          0x180
       
   731 #define MP_LCD_IRQSTAT          0x184
       
   732 #define MP_LCD_SPICTRL          0x1ac
       
   733 #define MP_LCD_INST             0x1bc
       
   734 #define MP_LCD_DATA             0x1c0
       
   735 
       
   736 /* Mode magics */
       
   737 #define MP_LCD_SPI_DATA         0x00100011
       
   738 #define MP_LCD_SPI_CMD          0x00104011
       
   739 #define MP_LCD_SPI_INVALID      0x00000000
       
   740 
       
   741 /* Commmands */
       
   742 #define MP_LCD_INST_SETPAGE0    0xB0
       
   743 /* ... */
       
   744 #define MP_LCD_INST_SETPAGE7    0xB7
       
   745 
       
   746 #define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
       
   747 
       
   748 typedef struct musicpal_lcd_state {
       
   749     uint32_t mode;
       
   750     uint32_t irqctrl;
       
   751     int page;
       
   752     int page_off;
       
   753     DisplayState *ds;
       
   754     uint8_t video_ram[128*64/8];
       
   755 } musicpal_lcd_state;
       
   756 
       
   757 static uint32_t lcd_brightness;
       
   758 
       
   759 static uint8_t scale_lcd_color(uint8_t col)
       
   760 {
       
   761     int tmp = col;
       
   762 
       
   763     switch (lcd_brightness) {
       
   764     case 0x00000007: /* 0 */
       
   765         return 0;
       
   766 
       
   767     case 0x00020000: /* 1 */
       
   768         return (tmp * 1) / 7;
       
   769 
       
   770     case 0x00020001: /* 2 */
       
   771         return (tmp * 2) / 7;
       
   772 
       
   773     case 0x00040000: /* 3 */
       
   774         return (tmp * 3) / 7;
       
   775 
       
   776     case 0x00010006: /* 4 */
       
   777         return (tmp * 4) / 7;
       
   778 
       
   779     case 0x00020005: /* 5 */
       
   780         return (tmp * 5) / 7;
       
   781 
       
   782     case 0x00040003: /* 6 */
       
   783         return (tmp * 6) / 7;
       
   784 
       
   785     case 0x00030004: /* 7 */
       
   786     default:
       
   787         return col;
       
   788     }
       
   789 }
       
   790 
       
   791 #define SET_LCD_PIXEL(depth, type) \
       
   792 static inline void glue(set_lcd_pixel, depth) \
       
   793         (musicpal_lcd_state *s, int x, int y, type col) \
       
   794 { \
       
   795     int dx, dy; \
       
   796     type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
       
   797 \
       
   798     for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
       
   799         for (dx = 0; dx < 3; dx++, pixel++) \
       
   800             *pixel = col; \
       
   801 }
       
   802 SET_LCD_PIXEL(8, uint8_t)
       
   803 SET_LCD_PIXEL(16, uint16_t)
       
   804 SET_LCD_PIXEL(32, uint32_t)
       
   805 
       
   806 #include "pixel_ops.h"
       
   807 
       
   808 static void lcd_refresh(void *opaque)
       
   809 {
       
   810     musicpal_lcd_state *s = opaque;
       
   811     int x, y, col;
       
   812 
       
   813     switch (ds_get_bits_per_pixel(s->ds)) {
       
   814     case 0:
       
   815         return;
       
   816 #define LCD_REFRESH(depth, func) \
       
   817     case depth: \
       
   818         col = func(scale_lcd_color((MP_LCD_TEXTCOLOR >> 16) & 0xff), \
       
   819                    scale_lcd_color((MP_LCD_TEXTCOLOR >> 8) & 0xff), \
       
   820                    scale_lcd_color(MP_LCD_TEXTCOLOR & 0xff)); \
       
   821         for (x = 0; x < 128; x++) \
       
   822             for (y = 0; y < 64; y++) \
       
   823                 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) \
       
   824                     glue(set_lcd_pixel, depth)(s, x, y, col); \
       
   825                 else \
       
   826                     glue(set_lcd_pixel, depth)(s, x, y, 0); \
       
   827         break;
       
   828     LCD_REFRESH(8, rgb_to_pixel8)
       
   829     LCD_REFRESH(16, rgb_to_pixel16)
       
   830     LCD_REFRESH(32, (ds_get_bgr(s->ds) ? rgb_to_pixel32bgr : rgb_to_pixel32))
       
   831     default:
       
   832         cpu_abort(cpu_single_env, "unsupported colour depth %i\n",
       
   833                   ds_get_bits_per_pixel(s->ds));
       
   834     }
       
   835 
       
   836     dpy_update(s->ds, 0, 0, 128*3, 64*3);
       
   837 }
       
   838 
       
   839 static void lcd_invalidate(void *opaque)
       
   840 {
       
   841 }
       
   842 
       
   843 static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset)
       
   844 {
       
   845     musicpal_lcd_state *s = opaque;
       
   846 
       
   847     switch (offset) {
       
   848     case MP_LCD_IRQCTRL:
       
   849         return s->irqctrl;
       
   850 
       
   851     default:
       
   852         return 0;
       
   853     }
       
   854 }
       
   855 
       
   856 static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset,
       
   857                                uint32_t value)
       
   858 {
       
   859     musicpal_lcd_state *s = opaque;
       
   860 
       
   861     switch (offset) {
       
   862     case MP_LCD_IRQCTRL:
       
   863         s->irqctrl = value;
       
   864         break;
       
   865 
       
   866     case MP_LCD_SPICTRL:
       
   867         if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD)
       
   868             s->mode = value;
       
   869         else
       
   870             s->mode = MP_LCD_SPI_INVALID;
       
   871         break;
       
   872 
       
   873     case MP_LCD_INST:
       
   874         if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
       
   875             s->page = value - MP_LCD_INST_SETPAGE0;
       
   876             s->page_off = 0;
       
   877         }
       
   878         break;
       
   879 
       
   880     case MP_LCD_DATA:
       
   881         if (s->mode == MP_LCD_SPI_CMD) {
       
   882             if (value >= MP_LCD_INST_SETPAGE0 &&
       
   883                 value <= MP_LCD_INST_SETPAGE7) {
       
   884                 s->page = value - MP_LCD_INST_SETPAGE0;
       
   885                 s->page_off = 0;
       
   886             }
       
   887         } else if (s->mode == MP_LCD_SPI_DATA) {
       
   888             s->video_ram[s->page*128 + s->page_off] = value;
       
   889             s->page_off = (s->page_off + 1) & 127;
       
   890         }
       
   891         break;
       
   892     }
       
   893 }
       
   894 
       
   895 static CPUReadMemoryFunc *musicpal_lcd_readfn[] = {
       
   896     musicpal_lcd_read,
       
   897     musicpal_lcd_read,
       
   898     musicpal_lcd_read
       
   899 };
       
   900 
       
   901 static CPUWriteMemoryFunc *musicpal_lcd_writefn[] = {
       
   902     musicpal_lcd_write,
       
   903     musicpal_lcd_write,
       
   904     musicpal_lcd_write
       
   905 };
       
   906 
       
   907 static void musicpal_lcd_init(DisplayState *ds, uint32_t base)
       
   908 {
       
   909     musicpal_lcd_state *s;
       
   910     int iomemtype;
       
   911 
       
   912     s = qemu_mallocz(sizeof(musicpal_lcd_state));
       
   913     if (!s)
       
   914         return;
       
   915     iomemtype = cpu_register_io_memory(0, musicpal_lcd_readfn,
       
   916                                        musicpal_lcd_writefn, s);
       
   917     cpu_register_physical_memory(base, MP_LCD_SIZE, iomemtype);
       
   918 
       
   919     s->ds = gui_get_graphic_console(NULL, lcd_refresh, lcd_invalidate,
       
   920                                     NULL, s);
       
   921     gui_resize_vt(s->ds, 128*3, 64*3);
       
   922 }
       
   923 
       
   924 /* PIC register offsets */
       
   925 #define MP_PIC_STATUS           0x00
       
   926 #define MP_PIC_ENABLE_SET       0x08
       
   927 #define MP_PIC_ENABLE_CLR       0x0C
       
   928 
       
   929 typedef struct mv88w8618_pic_state
       
   930 {
       
   931     uint32_t level;
       
   932     uint32_t enabled;
       
   933     qemu_irq parent_irq;
       
   934 } mv88w8618_pic_state;
       
   935 
       
   936 static void mv88w8618_pic_update(mv88w8618_pic_state *s)
       
   937 {
       
   938     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
       
   939 }
       
   940 
       
   941 static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
       
   942 {
       
   943     mv88w8618_pic_state *s = opaque;
       
   944 
       
   945     if (level)
       
   946         s->level |= 1 << irq;
       
   947     else
       
   948         s->level &= ~(1 << irq);
       
   949     mv88w8618_pic_update(s);
       
   950 }
       
   951 
       
   952 static uint32_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset)
       
   953 {
       
   954     mv88w8618_pic_state *s = opaque;
       
   955 
       
   956     switch (offset) {
       
   957     case MP_PIC_STATUS:
       
   958         return s->level & s->enabled;
       
   959 
       
   960     default:
       
   961         return 0;
       
   962     }
       
   963 }
       
   964 
       
   965 static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset,
       
   966                                 uint32_t value)
       
   967 {
       
   968     mv88w8618_pic_state *s = opaque;
       
   969 
       
   970     switch (offset) {
       
   971     case MP_PIC_ENABLE_SET:
       
   972         s->enabled |= value;
       
   973         break;
       
   974 
       
   975     case MP_PIC_ENABLE_CLR:
       
   976         s->enabled &= ~value;
       
   977         s->level &= ~value;
       
   978         break;
       
   979     }
       
   980     mv88w8618_pic_update(s);
       
   981 }
       
   982 
       
   983 static void mv88w8618_pic_reset(void *opaque)
       
   984 {
       
   985     mv88w8618_pic_state *s = opaque;
       
   986 
       
   987     s->level = 0;
       
   988     s->enabled = 0;
       
   989 }
       
   990 
       
   991 static CPUReadMemoryFunc *mv88w8618_pic_readfn[] = {
       
   992     mv88w8618_pic_read,
       
   993     mv88w8618_pic_read,
       
   994     mv88w8618_pic_read
       
   995 };
       
   996 
       
   997 static CPUWriteMemoryFunc *mv88w8618_pic_writefn[] = {
       
   998     mv88w8618_pic_write,
       
   999     mv88w8618_pic_write,
       
  1000     mv88w8618_pic_write
       
  1001 };
       
  1002 
       
  1003 static qemu_irq *mv88w8618_pic_init(uint32_t base, qemu_irq parent_irq)
       
  1004 {
       
  1005     mv88w8618_pic_state *s;
       
  1006     int iomemtype;
       
  1007     qemu_irq *qi;
       
  1008 
       
  1009     s = qemu_mallocz(sizeof(mv88w8618_pic_state));
       
  1010     if (!s)
       
  1011         return NULL;
       
  1012     qi = qemu_allocate_irqs(mv88w8618_pic_set_irq, s, 32);
       
  1013     s->parent_irq = parent_irq;
       
  1014     iomemtype = cpu_register_io_memory(0, mv88w8618_pic_readfn,
       
  1015                                        mv88w8618_pic_writefn, s);
       
  1016     cpu_register_physical_memory(base, MP_PIC_SIZE, iomemtype);
       
  1017 
       
  1018     qemu_register_reset(mv88w8618_pic_reset, s);
       
  1019 
       
  1020     return qi;
       
  1021 }
       
  1022 
       
  1023 /* PIT register offsets */
       
  1024 #define MP_PIT_TIMER1_LENGTH    0x00
       
  1025 /* ... */
       
  1026 #define MP_PIT_TIMER4_LENGTH    0x0C
       
  1027 #define MP_PIT_CONTROL          0x10
       
  1028 #define MP_PIT_TIMER1_VALUE     0x14
       
  1029 /* ... */
       
  1030 #define MP_PIT_TIMER4_VALUE     0x20
       
  1031 #define MP_BOARD_RESET          0x34
       
  1032 
       
  1033 /* Magic board reset value (probably some watchdog behind it) */
       
  1034 #define MP_BOARD_RESET_MAGIC    0x10000
       
  1035 
       
  1036 typedef struct mv88w8618_timer_state {
       
  1037     ptimer_state *timer;
       
  1038     uint32_t limit;
       
  1039     int freq;
       
  1040     qemu_irq irq;
       
  1041 } mv88w8618_timer_state;
       
  1042 
       
  1043 typedef struct mv88w8618_pit_state {
       
  1044     void *timer[4];
       
  1045     uint32_t control;
       
  1046 } mv88w8618_pit_state;
       
  1047 
       
  1048 static void mv88w8618_timer_tick(void *opaque)
       
  1049 {
       
  1050     mv88w8618_timer_state *s = opaque;
       
  1051 
       
  1052     qemu_irq_raise(s->irq);
       
  1053 }
       
  1054 
       
  1055 static void *mv88w8618_timer_init(uint32_t freq, qemu_irq irq)
       
  1056 {
       
  1057     mv88w8618_timer_state *s;
       
  1058     QEMUBH *bh;
       
  1059 
       
  1060     s = qemu_mallocz(sizeof(mv88w8618_timer_state));
       
  1061     s->irq = irq;
       
  1062     s->freq = freq;
       
  1063 
       
  1064     bh = qemu_bh_new(mv88w8618_timer_tick, s);
       
  1065     s->timer = ptimer_init(bh);
       
  1066 
       
  1067     return s;
       
  1068 }
       
  1069 
       
  1070 static uint32_t mv88w8618_pit_read(void *opaque, target_phys_addr_t offset)
       
  1071 {
       
  1072     mv88w8618_pit_state *s = opaque;
       
  1073     mv88w8618_timer_state *t;
       
  1074 
       
  1075     switch (offset) {
       
  1076     case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
       
  1077         t = s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
       
  1078         return ptimer_get_count(t->timer);
       
  1079 
       
  1080     default:
       
  1081         return 0;
       
  1082     }
       
  1083 }
       
  1084 
       
  1085 static void mv88w8618_pit_write(void *opaque, target_phys_addr_t offset,
       
  1086                                 uint32_t value)
       
  1087 {
       
  1088     mv88w8618_pit_state *s = opaque;
       
  1089     mv88w8618_timer_state *t;
       
  1090     int i;
       
  1091 
       
  1092     switch (offset) {
       
  1093     case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
       
  1094         t = s->timer[offset >> 2];
       
  1095         t->limit = value;
       
  1096         ptimer_set_limit(t->timer, t->limit, 1);
       
  1097         break;
       
  1098 
       
  1099     case MP_PIT_CONTROL:
       
  1100         for (i = 0; i < 4; i++) {
       
  1101             if (value & 0xf) {
       
  1102                 t = s->timer[i];
       
  1103                 ptimer_set_limit(t->timer, t->limit, 0);
       
  1104                 ptimer_set_freq(t->timer, t->freq);
       
  1105                 ptimer_run(t->timer, 0);
       
  1106             }
       
  1107             value >>= 4;
       
  1108         }
       
  1109         break;
       
  1110 
       
  1111     case MP_BOARD_RESET:
       
  1112         if (value == MP_BOARD_RESET_MAGIC)
       
  1113             qemu_system_reset_request();
       
  1114         break;
       
  1115     }
       
  1116 }
       
  1117 
       
  1118 static CPUReadMemoryFunc *mv88w8618_pit_readfn[] = {
       
  1119     mv88w8618_pit_read,
       
  1120     mv88w8618_pit_read,
       
  1121     mv88w8618_pit_read
       
  1122 };
       
  1123 
       
  1124 static CPUWriteMemoryFunc *mv88w8618_pit_writefn[] = {
       
  1125     mv88w8618_pit_write,
       
  1126     mv88w8618_pit_write,
       
  1127     mv88w8618_pit_write
       
  1128 };
       
  1129 
       
  1130 static void mv88w8618_pit_init(uint32_t base, qemu_irq *pic, int irq)
       
  1131 {
       
  1132     int iomemtype;
       
  1133     mv88w8618_pit_state *s;
       
  1134 
       
  1135     s = qemu_mallocz(sizeof(mv88w8618_pit_state));
       
  1136     if (!s)
       
  1137         return;
       
  1138 
       
  1139     /* Letting them all run at 1 MHz is likely just a pragmatic
       
  1140      * simplification. */
       
  1141     s->timer[0] = mv88w8618_timer_init(1000000, pic[irq]);
       
  1142     s->timer[1] = mv88w8618_timer_init(1000000, pic[irq + 1]);
       
  1143     s->timer[2] = mv88w8618_timer_init(1000000, pic[irq + 2]);
       
  1144     s->timer[3] = mv88w8618_timer_init(1000000, pic[irq + 3]);
       
  1145 
       
  1146     iomemtype = cpu_register_io_memory(0, mv88w8618_pit_readfn,
       
  1147                                        mv88w8618_pit_writefn, s);
       
  1148     cpu_register_physical_memory(base, MP_PIT_SIZE, iomemtype);
       
  1149 }
       
  1150 
       
  1151 /* Flash config register offsets */
       
  1152 #define MP_FLASHCFG_CFGR0    0x04
       
  1153 
       
  1154 typedef struct mv88w8618_flashcfg_state {
       
  1155     uint32_t cfgr0;
       
  1156 } mv88w8618_flashcfg_state;
       
  1157 
       
  1158 static uint32_t mv88w8618_flashcfg_read(void *opaque,
       
  1159                                         target_phys_addr_t offset)
       
  1160 {
       
  1161     mv88w8618_flashcfg_state *s = opaque;
       
  1162 
       
  1163     switch (offset) {
       
  1164     case MP_FLASHCFG_CFGR0:
       
  1165         return s->cfgr0;
       
  1166 
       
  1167     default:
       
  1168         return 0;
       
  1169     }
       
  1170 }
       
  1171 
       
  1172 static void mv88w8618_flashcfg_write(void *opaque, target_phys_addr_t offset,
       
  1173                                      uint32_t value)
       
  1174 {
       
  1175     mv88w8618_flashcfg_state *s = opaque;
       
  1176 
       
  1177     switch (offset) {
       
  1178     case MP_FLASHCFG_CFGR0:
       
  1179         s->cfgr0 = value;
       
  1180         break;
       
  1181     }
       
  1182 }
       
  1183 
       
  1184 static CPUReadMemoryFunc *mv88w8618_flashcfg_readfn[] = {
       
  1185     mv88w8618_flashcfg_read,
       
  1186     mv88w8618_flashcfg_read,
       
  1187     mv88w8618_flashcfg_read
       
  1188 };
       
  1189 
       
  1190 static CPUWriteMemoryFunc *mv88w8618_flashcfg_writefn[] = {
       
  1191     mv88w8618_flashcfg_write,
       
  1192     mv88w8618_flashcfg_write,
       
  1193     mv88w8618_flashcfg_write
       
  1194 };
       
  1195 
       
  1196 static void mv88w8618_flashcfg_init(uint32_t base)
       
  1197 {
       
  1198     int iomemtype;
       
  1199     mv88w8618_flashcfg_state *s;
       
  1200 
       
  1201     s = qemu_mallocz(sizeof(mv88w8618_flashcfg_state));
       
  1202     if (!s)
       
  1203         return;
       
  1204 
       
  1205     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
       
  1206     iomemtype = cpu_register_io_memory(0, mv88w8618_flashcfg_readfn,
       
  1207                        mv88w8618_flashcfg_writefn, s);
       
  1208     cpu_register_physical_memory(base, MP_FLASHCFG_SIZE, iomemtype);
       
  1209 }
       
  1210 
       
  1211 /* Various registers in the 0x80000000 domain */
       
  1212 #define MP_BOARD_REVISION       0x2018
       
  1213 
       
  1214 #define MP_WLAN_MAGIC1          0xc11c
       
  1215 #define MP_WLAN_MAGIC2          0xc124
       
  1216 
       
  1217 #define MP_GPIO_OE_LO           0xd008
       
  1218 #define MP_GPIO_OUT_LO          0xd00c
       
  1219 #define MP_GPIO_IN_LO           0xd010
       
  1220 #define MP_GPIO_ISR_LO          0xd020
       
  1221 #define MP_GPIO_OE_HI           0xd508
       
  1222 #define MP_GPIO_OUT_HI          0xd50c
       
  1223 #define MP_GPIO_IN_HI           0xd510
       
  1224 #define MP_GPIO_ISR_HI          0xd520
       
  1225 
       
  1226 /* GPIO bits & masks */
       
  1227 #define MP_GPIO_WHEEL_VOL       (1 << 8)
       
  1228 #define MP_GPIO_WHEEL_VOL_INV   (1 << 9)
       
  1229 #define MP_GPIO_WHEEL_NAV       (1 << 10)
       
  1230 #define MP_GPIO_WHEEL_NAV_INV   (1 << 11)
       
  1231 #define MP_GPIO_LCD_BRIGHTNESS  0x00070000
       
  1232 #define MP_GPIO_BTN_FAVORITS    (1 << 19)
       
  1233 #define MP_GPIO_BTN_MENU        (1 << 20)
       
  1234 #define MP_GPIO_BTN_VOLUME      (1 << 21)
       
  1235 #define MP_GPIO_BTN_NAVIGATION  (1 << 22)
       
  1236 #define MP_GPIO_I2C_DATA_BIT    29
       
  1237 #define MP_GPIO_I2C_DATA        (1 << MP_GPIO_I2C_DATA_BIT)
       
  1238 #define MP_GPIO_I2C_CLOCK_BIT   30
       
  1239 
       
  1240 /* LCD brightness bits in GPIO_OE_HI */
       
  1241 #define MP_OE_LCD_BRIGHTNESS    0x0007
       
  1242 
       
  1243 static uint32_t musicpal_read(void *opaque, target_phys_addr_t offset)
       
  1244 {
       
  1245     switch (offset) {
       
  1246     case MP_BOARD_REVISION:
       
  1247         return 0x0031;
       
  1248 
       
  1249     case MP_GPIO_OE_HI: /* used for LCD brightness control */
       
  1250         return lcd_brightness & MP_OE_LCD_BRIGHTNESS;
       
  1251 
       
  1252     case MP_GPIO_OUT_LO:
       
  1253         return gpio_out_state & 0xFFFF;
       
  1254     case MP_GPIO_OUT_HI:
       
  1255         return gpio_out_state >> 16;
       
  1256 
       
  1257     case MP_GPIO_IN_LO:
       
  1258         return gpio_in_state & 0xFFFF;
       
  1259     case MP_GPIO_IN_HI:
       
  1260         /* Update received I2C data */
       
  1261         gpio_in_state = (gpio_in_state & ~MP_GPIO_I2C_DATA) |
       
  1262                         (i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT);
       
  1263         return gpio_in_state >> 16;
       
  1264 
       
  1265     case MP_GPIO_ISR_LO:
       
  1266         return gpio_isr & 0xFFFF;
       
  1267     case MP_GPIO_ISR_HI:
       
  1268         return gpio_isr >> 16;
       
  1269 
       
  1270     /* Workaround to allow loading the binary-only wlandrv.ko crap
       
  1271      * from the original Freecom firmware. */
       
  1272     case MP_WLAN_MAGIC1:
       
  1273         return ~3;
       
  1274     case MP_WLAN_MAGIC2:
       
  1275         return -1;
       
  1276 
       
  1277     default:
       
  1278         return 0;
       
  1279     }
       
  1280 }
       
  1281 
       
  1282 static void musicpal_write(void *opaque, target_phys_addr_t offset,
       
  1283                            uint32_t value)
       
  1284 {
       
  1285     switch (offset) {
       
  1286     case MP_GPIO_OE_HI: /* used for LCD brightness control */
       
  1287         lcd_brightness = (lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
       
  1288                          (value & MP_OE_LCD_BRIGHTNESS);
       
  1289         break;
       
  1290 
       
  1291     case MP_GPIO_OUT_LO:
       
  1292         gpio_out_state = (gpio_out_state & 0xFFFF0000) | (value & 0xFFFF);
       
  1293         break;
       
  1294     case MP_GPIO_OUT_HI:
       
  1295         gpio_out_state = (gpio_out_state & 0xFFFF) | (value << 16);
       
  1296         lcd_brightness = (lcd_brightness & 0xFFFF) |
       
  1297                          (gpio_out_state & MP_GPIO_LCD_BRIGHTNESS);
       
  1298         i2c_state_update(mixer_i2c,
       
  1299                          (gpio_out_state >> MP_GPIO_I2C_DATA_BIT) & 1,
       
  1300                          (gpio_out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
       
  1301         break;
       
  1302 
       
  1303     }
       
  1304 }
       
  1305 
       
  1306 /* Keyboard codes & masks */
       
  1307 #define KEY_RELEASED            0x80
       
  1308 #define KEY_CODE                0x7f
       
  1309 
       
  1310 #define KEYCODE_TAB             0x0f
       
  1311 #define KEYCODE_ENTER           0x1c
       
  1312 #define KEYCODE_F               0x21
       
  1313 #define KEYCODE_M               0x32
       
  1314 
       
  1315 #define KEYCODE_EXTENDED        0xe0
       
  1316 #define KEYCODE_UP              0x48
       
  1317 #define KEYCODE_DOWN            0x50
       
  1318 #define KEYCODE_LEFT            0x4b
       
  1319 #define KEYCODE_RIGHT           0x4d
       
  1320 
       
  1321 static void musicpal_key_event(void *opaque, int keycode)
       
  1322 {
       
  1323     qemu_irq irq = opaque;
       
  1324     uint32_t event = 0;
       
  1325     static int kbd_extended;
       
  1326 
       
  1327     if (keycode == KEYCODE_EXTENDED) {
       
  1328         kbd_extended = 1;
       
  1329         return;
       
  1330     }
       
  1331 
       
  1332     if (kbd_extended)
       
  1333         switch (keycode & KEY_CODE) {
       
  1334         case KEYCODE_UP:
       
  1335             event = MP_GPIO_WHEEL_NAV | MP_GPIO_WHEEL_NAV_INV;
       
  1336             break;
       
  1337 
       
  1338         case KEYCODE_DOWN:
       
  1339             event = MP_GPIO_WHEEL_NAV;
       
  1340             break;
       
  1341 
       
  1342         case KEYCODE_LEFT:
       
  1343             event = MP_GPIO_WHEEL_VOL | MP_GPIO_WHEEL_VOL_INV;
       
  1344             break;
       
  1345 
       
  1346         case KEYCODE_RIGHT:
       
  1347             event = MP_GPIO_WHEEL_VOL;
       
  1348             break;
       
  1349         }
       
  1350     else {
       
  1351         switch (keycode & KEY_CODE) {
       
  1352         case KEYCODE_F:
       
  1353             event = MP_GPIO_BTN_FAVORITS;
       
  1354             break;
       
  1355 
       
  1356         case KEYCODE_TAB:
       
  1357             event = MP_GPIO_BTN_VOLUME;
       
  1358             break;
       
  1359 
       
  1360         case KEYCODE_ENTER:
       
  1361             event = MP_GPIO_BTN_NAVIGATION;
       
  1362             break;
       
  1363 
       
  1364         case KEYCODE_M:
       
  1365             event = MP_GPIO_BTN_MENU;
       
  1366             break;
       
  1367         }
       
  1368         /* Do not repeat already pressed buttons */
       
  1369         if (!(keycode & KEY_RELEASED) && !(gpio_in_state & event))
       
  1370             event = 0;
       
  1371     }
       
  1372 
       
  1373     if (event) {
       
  1374         if (keycode & KEY_RELEASED) {
       
  1375             gpio_in_state |= event;
       
  1376         } else {
       
  1377             gpio_in_state &= ~event;
       
  1378             gpio_isr = event;
       
  1379             qemu_irq_raise(irq);
       
  1380         }
       
  1381     }
       
  1382 
       
  1383     kbd_extended = 0;
       
  1384 }
       
  1385 
       
  1386 static CPUReadMemoryFunc *musicpal_readfn[] = {
       
  1387     musicpal_read,
       
  1388     musicpal_read,
       
  1389     musicpal_read,
       
  1390 };
       
  1391 
       
  1392 static CPUWriteMemoryFunc *musicpal_writefn[] = {
       
  1393     musicpal_write,
       
  1394     musicpal_write,
       
  1395     musicpal_write,
       
  1396 };
       
  1397 
       
  1398 static struct arm_boot_info musicpal_binfo = {
       
  1399     .loader_start = 0x0,
       
  1400     .board_id = 0x20e,
       
  1401 };
       
  1402 
       
  1403 static void musicpal_init(ram_addr_t ram_size, int vga_ram_size,
       
  1404                const char *boot_device, DisplayState *ds,
       
  1405                const char *kernel_filename, const char *kernel_cmdline,
       
  1406                const char *initrd_filename, const char *cpu_model)
       
  1407 {
       
  1408     CPUState *env;
       
  1409     qemu_irq *pic;
       
  1410     int index;
       
  1411     int iomemtype;
       
  1412     unsigned long flash_size;
       
  1413 
       
  1414     if (!cpu_model)
       
  1415         cpu_model = "arm926";
       
  1416 
       
  1417     env = cpu_init(cpu_model);
       
  1418     if (!env) {
       
  1419         fprintf(stderr, "Unable to find CPU definition\n");
       
  1420         exit(1);
       
  1421     }
       
  1422     pic = arm_pic_init_cpu(env);
       
  1423 
       
  1424     /* For now we use a fixed - the original - RAM size */
       
  1425     cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
       
  1426                                  qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
       
  1427 
       
  1428     sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
       
  1429     cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
       
  1430 
       
  1431     /* Catch various stuff not handled by separate subsystems */
       
  1432     iomemtype = cpu_register_io_memory(0, musicpal_readfn,
       
  1433                                        musicpal_writefn, env);
       
  1434     cpu_register_physical_memory(0x80000000, 0x10000, iomemtype);
       
  1435 
       
  1436     pic = mv88w8618_pic_init(MP_PIC_BASE, pic[ARM_PIC_CPU_IRQ]);
       
  1437     mv88w8618_pit_init(MP_PIT_BASE, pic, MP_TIMER1_IRQ);
       
  1438 
       
  1439     if (serial_hds[0])
       
  1440         serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
       
  1441                    serial_hds[0], 1);
       
  1442     if (serial_hds[1])
       
  1443         serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
       
  1444                    serial_hds[1], 1);
       
  1445 
       
  1446     /* Register flash */
       
  1447     index = drive_get_index(IF_PFLASH, 0, 0);
       
  1448     if (index != -1) {
       
  1449         flash_size = bdrv_getlength(drives_table[index].bdrv);
       
  1450         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
       
  1451             flash_size != 32*1024*1024) {
       
  1452             fprintf(stderr, "Invalid flash image size\n");
       
  1453             exit(1);
       
  1454         }
       
  1455 
       
  1456         /*
       
  1457          * The original U-Boot accesses the flash at 0xFE000000 instead of
       
  1458          * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
       
  1459          * image is smaller than 32 MB.
       
  1460          */
       
  1461         pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
       
  1462                               drives_table[index].bdrv, 0x10000,
       
  1463                               (flash_size + 0xffff) >> 16,
       
  1464                               MP_FLASH_SIZE_MAX / flash_size,
       
  1465                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
       
  1466                               0x5555, 0x2AAA);
       
  1467     }
       
  1468     mv88w8618_flashcfg_init(MP_FLASHCFG_BASE);
       
  1469 
       
  1470     musicpal_lcd_init(ds, MP_LCD_BASE);
       
  1471 
       
  1472     gui_register_dev_key_callback(musicpal_key_event, pic[MP_GPIO_IRQ]);
       
  1473 
       
  1474     mv88w8618_eth_init(&nd_table[0], MP_ETH_BASE, pic[MP_ETH_IRQ]);
       
  1475 
       
  1476     mixer_i2c = musicpal_audio_init(MP_AUDIO_BASE, pic[MP_AUDIO_IRQ]);
       
  1477 
       
  1478     musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
       
  1479     musicpal_binfo.kernel_filename = kernel_filename;
       
  1480     musicpal_binfo.kernel_cmdline = kernel_cmdline;
       
  1481     musicpal_binfo.initrd_filename = initrd_filename;
       
  1482     arm_load_kernel(env, &musicpal_binfo);
       
  1483 }
       
  1484 
       
  1485 QEMUMachine musicpal_machine = {
       
  1486     .name = "musicpal",
       
  1487     .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
       
  1488     .init = musicpal_init,
       
  1489     .ram_require = MP_RAM_DEFAULT_SIZE + MP_SRAM_SIZE +
       
  1490             MP_FLASH_SIZE_MAX + RAMSIZE_FIXED,
       
  1491 };