class syborg_timer(qemu.devclass): REG_ID = 0 REG_LATCH = 1 REG_DATA_LOW = 2 REG_DATA_HIGH = 3 def create(self): self.data = 0 self.offset = qemu.start_time() * 1000000 - qemu.get_clock() def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0004 elif offset == self.REG_DATA_LOW: return self.data & 0xffffffff elif offset == self.REG_DATA_HIGH: return (self.data >> 32) & 0xffffffff return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_LATCH: now = qemu.get_clock() if value >= 4: self.offset = self.data - now else: self.data = now + self.offset while value: self.data /= 1000 value -= 1 elif offset == self.REG_DATA_LOW: self.data = (self.data & ~0xffffffff) | value elif offset == self.REG_DATA_HIGH: self.data = (self.data & 0xffffffff) | (value << 32) def save(self, f): f.put_s64(self.offset) f.put_u64(self.data) def load(self, f): self.offset = f.get_s64() self.data = f.get_u64() # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 0 name = "syborg,rtc" properties = {}
if( self.transaction_direction == self.NVMEM_TRANSACTION_READ ): self.nvmemlib.nvmem_read( self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size ) elif( self.transaction_direction == self.NVMEM_TRANSACTION_WRITE ): self.nvmemlib.nvmem_write( self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size ) else: error_msg = "syborg_nvmemorydevice: Transaction direction not set!" sys.exit( error_msg ) self.transaction_offset_set = 0 self.transaction_size_set = 0 self.transaction_direction_set = 0 elif offset == self.R_NVMEM_SHARED_MEMORY_BASE: self.shared_memory_base = value elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE: self.shared_memory_size = value elif offset == self.R_NVMEM_ENABLE: if( value > 0 ): self.nvmemory_memregion = qemu.memregion( self.shared_memory_base, self.shared_memory_size ) self.nvmemory_sharedmemory_host_address = self.nvmemory_memregion.region_host_addr() print"syborg_nvmemorydevice: host addr: 0x%08x" % (self.nvmemory_sharedmemory_host_address) else: reg_write_error = "syborg_nvmemorydevice: Illegal register write to: ", offset sys.exit( reg_write_error ) # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,nvmemorydevice" properties = {"drive_size":DEFAULT_DRIVE_SIZE, "sector_size":DEVICE_SECTOR_SIZE, "drive_image_name":DRIVE_NAME} qemu.register_device(syborg_nvmemorydevice)
class syborg_usbtest(qemu.devclass): REG_ID = 0 REG_INT_ENABLE = 1 REG_DATA_TYPE = 2 REG_DMA_ADDR = 3 REG_DMA_SIZE = 4 def loadIMG(self): self.buf = open('test1.BMP', 'rb').read() self.bufC = open('test.BMP', 'rb').read() self.bmpsize = os.path.getsize('test1.BMP') self.Csize = os.path.getsize('test.BMP') def timertick(self): if self.cha == 0: compSize = self.bmpsize buf = self.buf self.cha = 1 else: compSize = self.Csize buf = self.bufC self.cha = 0 if self.dma_size < compSize: self.dma_size = 0 else: for x in buf: ch = ord(x) if self.dma_size > 0: self.dma_writeb(self.dma_addr, ch) self.dma_addr += 1 self.dma_size -= 1 self.set_irq_level(0, self.int_enable) def timer_on(self): self.ptimer = qemu.ptimer(self.timertick, 1) self.ptimer.run(0) def timer_off(self): self.ptimer.stop() self.set_irq_level(0, self.int_enable) def capturedata(self): if self.dma_size < self.Csize: self.dma_size = 0 else: for x in self.bufC: ch = ord(x) if self.dma_size > 0: self.dma_writeb(self.dma_addr, ch) self.dma_addr += 1 self.dma_size -= 1 self.set_irq_level(0, self.int_enable) def create(self): self.int_enable = 1 self.dma_addr = 0 self.dma_size = 0 self.cha = 0 self.loadIMG() def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_INT_ENABLE: self.int_enable = value if value == 1: if self.data_type == 0: self.timer_on() elif self.data_type == 1: self.capturedata() else: if self.data_type == 0: self.timer_off() elif self.data_type == 1: self.set_irq_level(0, self.int_enable) elif offset == self.REG_DATA_TYPE: self.data_type = value elif offset == self.REG_DMA_ADDR: self.dma_addr = value elif offset == self.REG_DMA_SIZE: self.dma_size = value def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc600f000 elif offset == self.REG_INT_ENABLE: return self.int_enable elif offset == self.REG_DMA_ADDR: return self.dma_addr elif offset == self.REG_DMA_SIZE: return self.dma_size return 0 def save(self, f): f.put_u32(self.int_enable) f.put_u32(self.dma_addr) f.put_u32(self.dma_size) def load(self, f): self.int_enable = f.get_u32() self.dma_addr = f.get_u32() self.dma_size = f.get_u32() # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,usbtest" properties = {"chardev": None}
class syborg_interrupt(qemu.devclass): REG_ID = 0 REG_STATUS = 1 REG_CURRENT = 2 REG_DISABLE_ALL = 3 REG_DISABLE = 4 REG_ENABLE = 5 REG_TOTAL = 6 def update(self): self.pending = self.level & self.enabled self.set_irq_level(0, len(self.pending) > 0) def set_input(self, n, level): if level: if n in self.level: return self.level.add(n) else: if n not in self.level: return self.level.discard(n) self.update() def create(self): self.num_inputs = self.properties["num-interrupts"] self.enabled = set() self.level = set() self.pending = set() self.create_interrupts(self.set_input, self.num_inputs) def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0000 elif offset == self.REG_STATUS: return len(self.pending) elif offset == self.REG_CURRENT: for i in range(self.num_inputs): if i in self.pending: return i return 0xffffffff elif offset == self.REG_TOTAL: return self.num_inputs return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_DISABLE_ALL: self.enabled = set() elif offset == self.REG_DISABLE: if (value < self.num_inputs): self.enabled.discard(value) elif offset == self.REG_ENABLE: if (value < self.num_inputs): self.enabled.add(value) self.update() def save(self, f): f.put_u32(self.num_inputs) for i in range(self.num_inputs): val = 0 if i in self.enabled: val |= 1 if i in self.level: val |= 2 f.put_u32(val) def load(self, f): val = f.get_u32() if val != self.num_inputs: raise ValueError, "Incorrect number of IRQs" self.level = set() self.enabled = set() for i in range(self.num_inputs): val = f.get_u32() if (val & 1) != 0: self.enabled.add(i) if (val & 2) != 0: self.level.add(i) self.update() # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,interrupt" properties = {"num-interrupts":64}
class syborg_pointer(qemu.devclass): REG_ID = 0 REG_LATCH = 1 REG_FIFO_COUNT = 2 REG_X = 3 REG_Y = 4 REG_Z = 5 REG_BUTTONS = 6 REG_INT_ENABLE = 7 REG_FIFO_SIZE = 8 class fifo_entry: def __init__(self, x, y, z, buttons): self.x = x self.y = y self.z = z self.buttons = buttons def update_irq(self): self.set_irq_level(0, (len(self.fifo) > 0) and self.int_enabled) def event(self, x, y, z, buttons): if len(self.fifo) < self.fifo_size: self.fifo.append(self.fifo_entry(x, y, z, buttons)) self.update_irq() def create(self): self.absolute = self.properties["absolute"] self.fifo_size = self.properties["fifo-size"] self.fifo = [] self.current = self.fifo_entry(0, 0, 0, 0) self.int_enabled = False qemu.register_mouse(self.event, self.absolute, self.name) def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0006 if self.absolute else 0xc51d0005 elif offset == self.REG_FIFO_COUNT: return len(self.fifo) elif offset == self.REG_X: return self.current.x elif offset == self.REG_Y: return self.current.y elif offset == self.REG_Z: return self.current.z elif offset == self.REG_BUTTONS: return self.current.buttons elif offset == self.REG_INT_ENABLE: return self.int_enabled elif offset == self.REG_FIFO_SIZE: return self.fifo_size return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_LATCH: if len(self.fifo) == 0: return self.current = self.fifo.pop(0) self.update_irq() elif offset == self.REG_INT_ENABLE: self.int_enabled = ((value & 1) != 0) self.update_irq() def save(self, f): f.put_u32(self.fifo_size) f.put_u32(self.int_enabled) f.put_u32(len(self.fifo) + 1) for d in [self.current] + self.fifo: f.put_u32(d.x) f.put_u32(d.y) f.put_u32(d.z) f.put_u32(d.buttons) def load(self, f): if self.fifo_size != f.get_u32(): raise ValueError, "fifo size mismatch" self.int_enabled = f.get_u32() n = f.get_u32() self.fifo = [] while n > 0: x = f.get_u32() y = f.get_u32() z = f.get_u32() buttons = f.get_u32() self.fifo.append(self.fifo_entry(x, y, z, buttons)) n -= 1 self.current = self.fifo.pop(0) # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,pointer" properties = {"fifo-size": 16, "absolute": 1}
class syborg_timer(qemu.devclass): REG_ID = 0 REG_RUNNING = 1 REG_ONESHOT = 2 REG_LIMIT = 3 REG_VALUE = 4 REG_INT_ENABLE = 5 REG_INT_STATUS = 6 REG_FREQ = 7 def update(self): self.set_irq_level(0, (self.int_status & self.int_enable) != 0) def timer_tick(self): self.int_status |= 1 if (self.oneshot): self.running = False self.update() def create(self): self.freq = self.properties["frequency"] if self.freq == 0: raise ValueError, "Zero/unset frequency" self.timer = qemu.ptimer(self.timer_tick, self.freq) self.running = False self.oneshot = False self.int_status = 0 self.int_enable = 0 self.limit = 0 def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0003 elif offset == self.REG_RUNNING: return 1 if self.running else 0 elif offset == self.REG_ONESHOT: return 1 if self.oneshot else 0 elif offset == self.REG_LIMIT: return self.limit elif offset == self.REG_VALUE: return self.timer.count elif offset == self.REG_INT_ENABLE: return self.int_enable elif offset == self.REG_INT_STATUS: return self.int_status elif offset == self.REG_FREQ: return self.freq return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_RUNNING: if self.running != (value != 0): self.running = (value != 0) if self.running: self.timer.run(self.oneshot) else: self.timer.stop() elif offset == self.REG_ONESHOT: if self.running: self.timer.stop() self.oneshot = (value != 0) if self.running: self.timer.run(self.oneshot) elif offset == self.REG_LIMIT: self.limit = value self.timer.set_limit(value, True) elif offset == self.REG_VALUE: self.timer.count = value elif offset == self.REG_INT_ENABLE: self.int_enable = value & 1 self.update() elif offset == self.REG_INT_STATUS: self.int_status &= ~value self.update() def save(self, f): f.put_u32(self.running) f.put_u32(self.oneshot) f.put_u32(self.limit) f.put_u32(self.int_status) f.put_u32(self.int_enable) self.timer.put(f) def load(self, f): self.running = (f.get_u32() != 0) self.oneshot = (f.get_u32() != 0) self.limit = f.get_u32() self.int_status = f.get_u32() self.int_enable = f.get_u32() self.timer.get(f) # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,timer" properties = {"frequency": 0}
class syborg_keyboard(qemu.devclass): REG_ID = 0 REG_DATA = 1 REG_FIFO_COUNT = 2 REG_INT_ENABLE = 3 REG_FIFO_SIZE = 4 def update_irq(self): self.set_irq_level(0, (len(self.fifo) > 0) and self.int_enabled) def event(self, keycode): if (keycode == 0xe0) and not self.extension_bit: self.extension_bit = 0x80 return val = (keycode & 0x7f) | self.extension_bit if (keycode & 0x80) != 0: val |= 0x80000000 self.extension_bit = 0 if len(self.fifo) < self.fifo_size: self.fifo.append(val) self.update_irq() def create(self): self.fifo_size = self.properties["fifo-size"] self.fifo = [] self.int_enabled = False self.extension_bit = 0 qemu.register_keyboard(self.event) def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0002 elif offset == self.REG_DATA: if len(self.fifo) == 0: return 0xffffffff val = self.fifo.pop(0) self.update_irq() return val elif offset == self.REG_FIFO_COUNT: return len(self.fifo) elif offset == self.REG_INT_ENABLE: return self.int_enabled elif offset == self.REG_FIFO_SIZE: return self.fifo_size return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_INT_ENABLE: self.int_enabled = ((value & 1) != 0) self.update_irq() def save(self, f): f.put_u32(self.fifo_size) f.put_u32(self.int_enabled) f.put_u32(self.extension_bit) f.put_u32(len(self.fifo)) for x in self.fifo: f.put_u32(x) def load(self, f): if self.fifo_size != f.get_u32(): raise ValueError, "fifo size mismatch" self.int_enabled = f.get_u32() self.extension_bit = f.get_u32() n = f.get_u32() self.fifo = [] while n > 0: self.fifo.append(f.get_u32()) n -= 1 # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,keyboard" properties = {"fifo-size": 16}
class syborg_serial(qemu.devclass): REG_ID = 0 REG_DATA = 1 REG_FIFO_COUNT = 2 REG_INT_ENABLE = 3 REG_DMA_TX_ADDR = 4 REG_DMA_TX_COUNT = 5 # triggers dma REG_DMA_RX_ADDR = 6 REG_DMA_RX_COUNT = 7 # triggers dma def update_irq(self): level = 2 # TX DMA complete if len(self.fifo) > 0: level |= 1 # FIFO not empty if self.dma_rx_count == 0: level |= 4 # RX DMA complete self.set_irq_level(0, (level & self.int_enable) != 0) def can_receive(self): return self.fifo_size - len(self.fifo) def receive(self, buf): for x in buf: ch = ord(x) if self.dma_rx_count > 0: self.dma_writeb(self.dma_rx_addr, ch) self.dma_rx_addr += 1 self.dma_rx_count -= 1 else: self.fifo.append(ch) self.update_irq() def do_dma_tx(self, count): # TODO: Optimize block transmits. while count > 0: ch = self.dma_readb(self.dma_tx_addr) self.chardev.write(ch) self.dma_tx_addr += 1 count -= 1 self.update_irq() def dma_rx_start(self, count): while (count > 0) and (len(self.fifo) > 0): ch = self.fifo.pop(0) self.dma_writeb(self.dma_rx_addr, ch) self.dma_rx_addr += 1 count -= 1 self.dma_rx_count = count self.update_irq() def create(self): self.fifo_size = self.properties["fifo-size"] self.chardev = self.properties["chardev"] self.fifo = [] self.int_enable = 0 self.chardev.set_handlers(self.can_receive, self.receive) self.dma_tx_addr = 0 self.dma_rx_addr = 0 self.dma_rx_count = 0 def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0001 elif offset == self.REG_DATA: if len(self.fifo) == 0: return 0xffffffff val = self.fifo.pop(0) self.update_irq() return val elif offset == self.REG_FIFO_COUNT: return len(self.fifo) elif offset == self.REG_INT_ENABLE: return self.int_enable elif offset == self.REG_DMA_TX_ADDR: return self.dma_tx_addr elif offset == self.REG_DMA_TX_COUNT: return 0 elif offset == self.REG_DMA_RX_ADDR: return self.dma_rx_addr elif offset == self.REG_DMA_RX_COUNT: return self.dma_rx_count return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_DATA: self.chardev.write(value) elif offset == self.REG_INT_ENABLE: self.int_enable = value & 7 self.update_irq() elif offset == self.REG_DMA_TX_ADDR: self.dma_tx_addr = value elif offset == self.REG_DMA_TX_COUNT: self.do_dma_tx(value) elif offset == self.REG_DMA_RX_ADDR: self.dma_rx_addr = value elif offset == self.REG_DMA_RX_COUNT: self.dma_rx_start(value) def save(self, f): f.put_u32(self.fifo_size) f.put_u32(self.int_enable) f.put_u32(self.dma_tx_addr) f.put_u32(self.dma_rx_addr) f.put_u32(self.dma_rx_count) f.put_u32(len(self.fifo)) for x in self.fifo: f.put_u32(x) def load(self, f): if self.fifo_size != f.get_u32(): raise ValueError, "fifo size mismatch" self.int_enable = f.get_u32() self.dma_tx_addr = f.get_u32() self.dma_rx_addr = f.get_u32() self.dma_rx_count = f.get_u32() n = f.get_u32() self.fifo = [] while n > 0: self.fifo.append(f.get_u32()) n -= 1 # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,serial" properties = {"fifo-size": 16, "chardev": None, "target": ""}
class syborg_fb(qemu.devclass): REG_ID = 0 REG_BASE = 1 REG_HEIGHT = 2 REG_WIDTH = 3 REG_ORIENTATION = 4 REG_BLANK = 5 REG_INT_MASK = 6 REG_INT_CAUSE = 7 REG_BPP = 8 REG_COLOR_ORDER = 9 REG_BYTE_ORDER = 10 REG_PIXEL_ORDER = 11 REG_ROW_PITCH = 12 REG_ENABLED = 13 REG_PALETTE = 0x100 INT_VSYNC = (1 << 0) INT_BASE_UPDATE = (1 << 1) def update_irq(self): self.set_irq_level(0, (self.int_status & self.int_enable) != 0) def do_update(self): old_status = self.int_status if self.need_int: self.int_status |= self.INT_BASE_UPDATE self.need_int = False if self.render.blank == 0: self.int_status |= self.INT_VSYNC if self.int_status != old_status: self.update_irq() return self.enabled def create(self): self.enabled = False self.int_status = 0 self.int_enable = 0 self.need_int = True width = self.properties["width"] height = self.properties["height"] self.render = qemu.render(self.name, width, height) self.render.update = self.do_update def read_reg(self, offset): offset >>= 2 if offset == self.REG_ID: return 0xc51d0006 elif offset == self.REG_BASE: return self.render.base; elif offset == self.REG_WIDTH: return self.render.width; elif offset == self.REG_HEIGHT: return self.render.height; elif offset == self.REG_ORIENTATION: return self.render.orientation; elif offset == self.REG_BLANK: return self.render.blank; elif offset == self.REG_INT_MASK: return self.int_enable; elif offset == self.REG_INT_CAUSE: return self.int_status; elif offset == self.REG_BPP: return self.render.bpp; elif offset == self.REG_COLOR_ORDER: return self.render.color_order; elif offset == self.REG_BYTE_ORDER: return self.render.byte_order; elif offset == self.REG_PIXEL_ORDER: return self.render.pixel_order; elif offset == self.REG_ROW_PITCH: return self.render.row_pitch; elif offset == self.REG_ENABLED: return 1 if self.enabled else 0; elif (offset >= self.REG_PALETTE) and (offset < self.REG_PALETTE + 256): return self.render.palette[offset - self.REG_PALETTE]; return 0 def write_reg(self, offset, value): offset >>= 2 if offset == self.REG_BASE: self.render.base = value; self.need_int = True elif offset == self.REG_WIDTH: self.render.width = value; elif offset == self.REG_HEIGHT: self.render.height = value; elif offset == self.REG_ORIENTATION: self.render.orientation = value; elif offset == self.REG_BLANK: self.render.blank = value; elif offset == self.REG_INT_CAUSE: self.int_status &= ~value; self.update_irq() elif offset == self.REG_INT_MASK: self.int_enable = value & 3; self.update_irq() elif offset == self.REG_BPP: self.render.bpp = value; elif offset == self.REG_COLOR_ORDER: self.render.color_order = value; elif offset == self.REG_BYTE_ORDER: self.render.byte_order = value; elif offset == self.REG_PIXEL_ORDER: self.render.pixel_order = value; elif offset == self.REG_ROW_PITCH: self.render.row_pitch = value; elif offset == self.REG_ENABLED: self.enabled = value != 0; elif (offset >= self.REG_PALETTE) and (offset < self.REG_PALETTE + 256): self.render.palette[offset - self.REG_PALETTE] = value; def save(self, f): f.put_u32(1 if self.need_int else 0) f.put_u32(self.int_status) f.put_u32(self.int_enable) f.put_u32(1 if self.enabled else 0) self.render.put(f) def load(self, f): self.need_int = (f.get_u32() != 0) self.int_status = f.get_u32(); self.int_enable = f.get_u32(); self.enabled = (f.get_u32() != 0) self.render.get(f) # Device class properties regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,framebuffer" properties = {"width":0, "height":0}