musicpal.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,510 行 · 第 1/3 页

C
1,510
字号
/* PHY registers */#define MP_ETH_PHY1_BMSR        0x00210000#define MP_ETH_PHY1_PHYSID1     0x00410000#define MP_ETH_PHY1_PHYSID2     0x00610000#define MP_PHY_BMSR_LINK        0x0004#define MP_PHY_BMSR_AUTONEG     0x0008#define MP_PHY_88E3015          0x01410E20/* TX descriptor status */#define MP_ETH_TX_OWN           (1 << 31)/* RX descriptor status */#define MP_ETH_RX_OWN           (1 << 31)/* Interrupt cause/mask bits */#define MP_ETH_IRQ_RX_BIT       0#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)#define MP_ETH_IRQ_TXHI_BIT     2#define MP_ETH_IRQ_TXLO_BIT     3/* Port config bits */#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix *//* SDMA command bits */#define MP_ETH_CMD_TXHI         (1 << 23)#define MP_ETH_CMD_TXLO         (1 << 22)typedef struct mv88w8618_tx_desc {    uint32_t cmdstat;    uint16_t res;    uint16_t bytes;    uint32_t buffer;    uint32_t next;} mv88w8618_tx_desc;typedef struct mv88w8618_rx_desc {    uint32_t cmdstat;    uint16_t bytes;    uint16_t buffer_size;    uint32_t buffer;    uint32_t next;} mv88w8618_rx_desc;typedef struct mv88w8618_eth_state {    uint32_t base;    qemu_irq irq;    uint32_t smir;    uint32_t icr;    uint32_t imr;    int vlan_header;    mv88w8618_tx_desc *tx_queue[2];    mv88w8618_rx_desc *rx_queue[4];    mv88w8618_rx_desc *frx_queue[4];    mv88w8618_rx_desc *cur_rx[4];    VLANClientState *vc;} mv88w8618_eth_state;static int eth_can_receive(void *opaque){    return 1;}static void eth_receive(void *opaque, const uint8_t *buf, int size){    mv88w8618_eth_state *s = opaque;    mv88w8618_rx_desc *desc;    int i;    for (i = 0; i < 4; i++) {        desc = s->cur_rx[i];        if (!desc)            continue;        do {            if (le32_to_cpu(desc->cmdstat) & MP_ETH_RX_OWN &&                le16_to_cpu(desc->buffer_size) >= size) {                memcpy(target2host_addr(le32_to_cpu(desc->buffer) +                                        s->vlan_header),                       buf, size);                desc->bytes = cpu_to_le16(size + s->vlan_header);                desc->cmdstat &= cpu_to_le32(~MP_ETH_RX_OWN);                s->cur_rx[i] = target2host_addr(le32_to_cpu(desc->next));                s->icr |= MP_ETH_IRQ_RX;                if (s->icr & s->imr)                    qemu_irq_raise(s->irq);                return;            }            desc = target2host_addr(le32_to_cpu(desc->next));        } while (desc != s->rx_queue[i]);    }}static void eth_send(mv88w8618_eth_state *s, int queue_index){    mv88w8618_tx_desc *desc = s->tx_queue[queue_index];    do {        if (le32_to_cpu(desc->cmdstat) & MP_ETH_TX_OWN) {            qemu_send_packet(s->vc,                             target2host_addr(le32_to_cpu(desc->buffer)),                             le16_to_cpu(desc->bytes));            desc->cmdstat &= cpu_to_le32(~MP_ETH_TX_OWN);            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);        }        desc = target2host_addr(le32_to_cpu(desc->next));    } while (desc != s->tx_queue[queue_index]);}static uint32_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset){    mv88w8618_eth_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_ETH_SMIR:        if (s->smir & MP_ETH_SMIR_OPCODE) {            switch (s->smir & MP_ETH_SMIR_ADDR) {            case MP_ETH_PHY1_BMSR:                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |                       MP_ETH_SMIR_RDVALID;            case MP_ETH_PHY1_PHYSID1:                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;            case MP_ETH_PHY1_PHYSID2:                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;            default:                return MP_ETH_SMIR_RDVALID;            }        }        return 0;    case MP_ETH_ICR:        return s->icr;    case MP_ETH_IMR:        return s->imr;    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:        return host2target_addr(s->frx_queue[(offset - MP_ETH_FRDP0)/4]);    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:        return host2target_addr(s->rx_queue[(offset - MP_ETH_CRDP0)/4]);    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:        return host2target_addr(s->tx_queue[(offset - MP_ETH_CTDP0)/4]);    default:        return 0;    }}static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,                                uint32_t value){    mv88w8618_eth_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_ETH_SMIR:        s->smir = value;        break;    case MP_ETH_PCXR:        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;        break;    case MP_ETH_SDCMR:        if (value & MP_ETH_CMD_TXHI)            eth_send(s, 1);        if (value & MP_ETH_CMD_TXLO)            eth_send(s, 0);        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr)            qemu_irq_raise(s->irq);        break;    case MP_ETH_ICR:        s->icr &= value;        break;    case MP_ETH_IMR:        s->imr = value;        if (s->icr & s->imr)            qemu_irq_raise(s->irq);        break;    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = target2host_addr(value);        break;    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = target2host_addr(value);        break;    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = target2host_addr(value);        break;    }}static CPUReadMemoryFunc *mv88w8618_eth_readfn[] = {    mv88w8618_eth_read,    mv88w8618_eth_read,    mv88w8618_eth_read};static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {    mv88w8618_eth_write,    mv88w8618_eth_write,    mv88w8618_eth_write};static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq){    mv88w8618_eth_state *s;    int iomemtype;    s = qemu_mallocz(sizeof(mv88w8618_eth_state));    if (!s)        return;    s->base = base;    s->irq = irq;    s->vc = qemu_new_vlan_client(nd->vlan, eth_receive, eth_can_receive, s);    iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,                                       mv88w8618_eth_writefn, s);    cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);}/* LCD register offsets */#define MP_LCD_IRQCTRL          0x180#define MP_LCD_IRQSTAT          0x184#define MP_LCD_SPICTRL          0x1ac#define MP_LCD_INST             0x1bc#define MP_LCD_DATA             0x1c0/* Mode magics */#define MP_LCD_SPI_DATA         0x00100011#define MP_LCD_SPI_CMD          0x00104011#define MP_LCD_SPI_INVALID      0x00000000/* Commmands */#define MP_LCD_INST_SETPAGE0    0xB0/* ... */#define MP_LCD_INST_SETPAGE7    0xB7#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */typedef struct musicpal_lcd_state {    uint32_t base;    uint32_t mode;    uint32_t irqctrl;    int page;    int page_off;    DisplayState *ds;    uint8_t video_ram[128*64/8];} musicpal_lcd_state;static uint32_t lcd_brightness;static uint8_t scale_lcd_color(uint8_t col){    int tmp = col;    switch (lcd_brightness) {    case 0x00000007: /* 0 */        return 0;    case 0x00020000: /* 1 */        return (tmp * 1) / 7;    case 0x00020001: /* 2 */        return (tmp * 2) / 7;    case 0x00040000: /* 3 */        return (tmp * 3) / 7;    case 0x00010006: /* 4 */        return (tmp * 4) / 7;    case 0x00020005: /* 5 */        return (tmp * 5) / 7;    case 0x00040003: /* 6 */        return (tmp * 6) / 7;    case 0x00030004: /* 7 */    default:        return col;    }}#define SET_LCD_PIXEL(depth, type) \static inline void glue(set_lcd_pixel, depth) \        (musicpal_lcd_state *s, int x, int y, type col) \{ \    int dx, dy; \    type *pixel = &((type *) s->ds->data)[(y * 128 * 3 + x) * 3]; \\    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \        for (dx = 0; dx < 3; dx++, pixel++) \            *pixel = col; \}SET_LCD_PIXEL(8, uint8_t)SET_LCD_PIXEL(16, uint16_t)SET_LCD_PIXEL(32, uint32_t)#include "pixel_ops.h"static void lcd_refresh(void *opaque){    musicpal_lcd_state *s = opaque;    int x, y, col;    switch (s->ds->depth) {    case 0:        return;#define LCD_REFRESH(depth, func) \    case depth: \        col = func(scale_lcd_color((MP_LCD_TEXTCOLOR >> 16) & 0xff), \                   scale_lcd_color((MP_LCD_TEXTCOLOR >> 8) & 0xff), \                   scale_lcd_color(MP_LCD_TEXTCOLOR & 0xff)); \        for (x = 0; x < 128; x++) \            for (y = 0; y < 64; y++) \                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) \                    glue(set_lcd_pixel, depth)(s, x, y, col); \                else \                    glue(set_lcd_pixel, depth)(s, x, y, 0); \        break;    LCD_REFRESH(8, rgb_to_pixel8)    LCD_REFRESH(16, rgb_to_pixel16)    LCD_REFRESH(32, (s->ds->bgr ? rgb_to_pixel32bgr : rgb_to_pixel32))    default:        cpu_abort(cpu_single_env, "unsupported colour depth %i\n",                  s->ds->depth);    }    dpy_update(s->ds, 0, 0, 128*3, 64*3);}static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset){    musicpal_lcd_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_LCD_IRQCTRL:        return s->irqctrl;    default:        return 0;    }}static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset,                               uint32_t value){    musicpal_lcd_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_LCD_IRQCTRL:        s->irqctrl = value;        break;    case MP_LCD_SPICTRL:        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD)            s->mode = value;        else            s->mode = MP_LCD_SPI_INVALID;        break;    case MP_LCD_INST:        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {            s->page = value - MP_LCD_INST_SETPAGE0;            s->page_off = 0;        }        break;    case MP_LCD_DATA:        if (s->mode == MP_LCD_SPI_CMD) {            if (value >= MP_LCD_INST_SETPAGE0 &&                value <= MP_LCD_INST_SETPAGE7) {                s->page = value - MP_LCD_INST_SETPAGE0;                s->page_off = 0;            }        } else if (s->mode == MP_LCD_SPI_DATA) {            s->video_ram[s->page*128 + s->page_off] = value;            s->page_off = (s->page_off + 1) & 127;        }        break;    }}static CPUReadMemoryFunc *musicpal_lcd_readfn[] = {    musicpal_lcd_read,    musicpal_lcd_read,    musicpal_lcd_read};static CPUWriteMemoryFunc *musicpal_lcd_writefn[] = {    musicpal_lcd_write,    musicpal_lcd_write,    musicpal_lcd_write};static void musicpal_lcd_init(DisplayState *ds, uint32_t base){    musicpal_lcd_state *s;    int iomemtype;    s = qemu_mallocz(sizeof(musicpal_lcd_state));    if (!s)        return;    s->base = base;    s->ds = ds;    iomemtype = cpu_register_io_memory(0, musicpal_lcd_readfn,                                       musicpal_lcd_writefn, s);    cpu_register_physical_memory(base, MP_LCD_SIZE, iomemtype);    graphic_console_init(ds, lcd_refresh, NULL, NULL, NULL, s);    dpy_resize(ds, 128*3, 64*3);}/* PIC register offsets */#define MP_PIC_STATUS           0x00#define MP_PIC_ENABLE_SET       0x08#define MP_PIC_ENABLE_CLR       0x0Ctypedef struct mv88w8618_pic_state{    uint32_t base;    uint32_t level;    uint32_t enabled;    qemu_irq parent_irq;} mv88w8618_pic_state;static void mv88w8618_pic_update(mv88w8618_pic_state *s){    qemu_set_irq(s->parent_irq, (s->level & s->enabled));}static void mv88w8618_pic_set_irq(void *opaque, int irq, int level){    mv88w8618_pic_state *s = opaque;    if (level)        s->level |= 1 << irq;    else        s->level &= ~(1 << irq);    mv88w8618_pic_update(s);}static uint32_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset){    mv88w8618_pic_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_PIC_STATUS:        return s->level & s->enabled;    default:        return 0;    }}static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset,                                uint32_t value){    mv88w8618_pic_state *s = opaque;    offset -= s->base;    switch (offset) {    case MP_PIC_ENABLE_SET:        s->enabled |= value;        break;    case MP_PIC_ENABLE_CLR:        s->enabled &= ~value;        s->level &= ~value;        break;    }    mv88w8618_pic_update(s);}static void mv88w8618_pic_reset(void *opaque){    mv88w8618_pic_state *s = opaque;    s->level = 0;    s->enabled = 0;}static CPUReadMemoryFunc *mv88w8618_pic_readfn[] = {    mv88w8618_pic_read,    mv88w8618_pic_read,    mv88w8618_pic_read};static CPUWriteMemoryFunc *mv88w8618_pic_writefn[] = {    mv88w8618_pic_write,    mv88w8618_pic_write,    mv88w8618_pic_write

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?