symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_serial.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 import qemu
       
     2 
       
     3 class syborg_serial(qemu.devclass):
       
     4   REG_ID           = 0
       
     5   REG_DATA         = 1
       
     6   REG_FIFO_COUNT   = 2
       
     7   REG_INT_ENABLE   = 3
       
     8   REG_DMA_TX_ADDR  = 4
       
     9   REG_DMA_TX_COUNT = 5 # triggers dma
       
    10   REG_DMA_RX_ADDR  = 6
       
    11   REG_DMA_RX_COUNT = 7 # triggers dma
       
    12 
       
    13   def update_irq(self):
       
    14     level = 2 # TX DMA complete
       
    15     if len(self.fifo) > 0:
       
    16       level |= 1 # FIFO not empty
       
    17     if self.dma_rx_count == 0:
       
    18       level |= 4 # RX DMA complete
       
    19     self.set_irq_level(0, (level & self.int_enable) != 0)
       
    20 
       
    21   def can_receive(self):
       
    22     return self.fifo_size - len(self.fifo)
       
    23 
       
    24   def receive(self, buf):
       
    25     for x in buf:
       
    26       ch = ord(x)
       
    27       if self.dma_rx_count > 0:
       
    28         self.dma_writeb(self.dma_rx_addr, ch)
       
    29         self.dma_rx_addr += 1
       
    30         self.dma_rx_count -= 1
       
    31       else:
       
    32         self.fifo.append(ch)
       
    33     self.update_irq()
       
    34 
       
    35   def do_dma_tx(self, count):
       
    36     # TODO: Optimize block transmits.
       
    37     while count > 0:
       
    38       ch = self.dma_readb(self.dma_tx_addr)
       
    39       self.chardev.write(ch)
       
    40       self.dma_tx_addr += 1
       
    41       count -= 1
       
    42     self.update_irq()
       
    43 
       
    44   def dma_rx_start(self, count):
       
    45     while (count > 0) and (len(self.fifo) > 0):
       
    46       ch = self.fifo.pop(0)
       
    47       self.dma_writeb(self.dma_rx_addr, ch)
       
    48       self.dma_rx_addr += 1
       
    49       count -= 1
       
    50     self.dma_rx_count = count
       
    51     self.update_irq()
       
    52 
       
    53   def create(self):
       
    54     self.fifo_size = self.properties["fifo-size"]
       
    55     self.chardev = self.properties["chardev"]
       
    56     self.fifo=[]
       
    57     self.int_enable = 0
       
    58     self.chardev.set_handlers(self.can_receive, self.receive)
       
    59     self.dma_tx_addr = 0
       
    60     self.dma_rx_addr = 0
       
    61     self.dma_rx_count = 0
       
    62 
       
    63   def read_reg(self, offset):
       
    64     offset >>= 2
       
    65     if offset == self.REG_ID:
       
    66       return 0xc51d0001
       
    67     elif offset == self.REG_DATA:
       
    68       if len(self.fifo) == 0:
       
    69         return 0xffffffff
       
    70       val = self.fifo.pop(0)
       
    71       self.update_irq();
       
    72       return val
       
    73     elif offset == self.REG_FIFO_COUNT:
       
    74       return len(self.fifo)
       
    75     elif offset == self.REG_INT_ENABLE:
       
    76       return self.int_enable
       
    77     elif offset == self.REG_DMA_TX_ADDR:
       
    78       return self.dma_tx_addr
       
    79     elif offset == self.REG_DMA_TX_COUNT:
       
    80       return 0
       
    81     elif offset == self.REG_DMA_RX_ADDR:
       
    82       return self.dma_rx_addr
       
    83     elif offset == self.REG_DMA_RX_COUNT:
       
    84       return self.dma_rx_count
       
    85     return 0
       
    86 
       
    87   def write_reg(self, offset, value):
       
    88     offset >>= 2
       
    89     if offset == self.REG_DATA:
       
    90       self.chardev.write(value)
       
    91     elif offset == self.REG_INT_ENABLE:
       
    92       self.int_enable = value & 7
       
    93       self.update_irq()
       
    94     elif offset == self.REG_DMA_TX_ADDR:
       
    95       self.dma_tx_addr = value
       
    96     elif offset == self.REG_DMA_TX_COUNT:
       
    97       self.do_dma_tx(value)
       
    98     elif offset == self.REG_DMA_RX_ADDR:
       
    99       self.dma_rx_addr = value
       
   100     elif offset == self.REG_DMA_RX_COUNT:
       
   101       self.dma_rx_start(value)
       
   102 
       
   103   def save(self, f):
       
   104     f.put_u32(self.fifo_size)
       
   105     f.put_u32(self.int_enable)
       
   106     f.put_u32(self.dma_tx_addr)
       
   107     f.put_u32(self.dma_rx_addr)
       
   108     f.put_u32(self.dma_rx_count)
       
   109     f.put_u32(len(self.fifo))
       
   110     for x in self.fifo:
       
   111       f.put_u32(x)
       
   112 
       
   113   def load(self, f):
       
   114     if self.fifo_size != f.get_u32():
       
   115       raise ValueError, "fifo size mismatch"
       
   116     self.int_enable = f.get_u32()
       
   117     self.dma_tx_addr = f.get_u32()
       
   118     self.dma_rx_addr = f.get_u32()
       
   119     self.dma_rx_count = f.get_u32()
       
   120     n = f.get_u32()
       
   121     self.fifo = []
       
   122     while n > 0:
       
   123       self.fifo.append(f.get_u32())
       
   124       n -= 1;
       
   125 
       
   126   # Device class properties
       
   127   regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)]
       
   128   irqs = 1
       
   129   name = "syborg,serial"
       
   130   properties = {"fifo-size":16, "chardev":None}
       
   131 
       
   132 qemu.register_device(syborg_serial)