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 + -
显示快捷键?