symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/i2c.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU I2C bus interface.
       
     3  *
       
     4  * Copyright (c) 2007 CodeSourcery.
       
     5  * Written by Paul Brook
       
     6  *
       
     7  * This code is licenced under the LGPL.
       
     8  */
       
     9 
       
    10 #include "hw.h"
       
    11 #include "i2c.h"
       
    12 
       
    13 struct i2c_bus
       
    14 {
       
    15     i2c_slave *current_dev;
       
    16     i2c_slave *dev;
       
    17     int saved_address;
       
    18 };
       
    19 
       
    20 static void i2c_bus_save(QEMUFile *f, void *opaque)
       
    21 {
       
    22     i2c_bus *bus = (i2c_bus *)opaque;
       
    23 
       
    24     qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : -1);
       
    25 }
       
    26 
       
    27 static int i2c_bus_load(QEMUFile *f, void *opaque, int version_id)
       
    28 {
       
    29     i2c_bus *bus = (i2c_bus *)opaque;
       
    30 
       
    31     if (version_id != 1)
       
    32         return -EINVAL;
       
    33 
       
    34     /* The bus is loaded before attached devices, so load and save the
       
    35        current device id.  Devices will check themselves as loaded.  */
       
    36     bus->saved_address = (int8_t) qemu_get_byte(f);
       
    37     bus->current_dev = NULL;
       
    38 
       
    39     return 0;
       
    40 }
       
    41 
       
    42 /* Create a new I2C bus.  */
       
    43 i2c_bus *i2c_init_bus(void)
       
    44 {
       
    45     i2c_bus *bus;
       
    46 
       
    47     bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
       
    48     register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus);
       
    49     return bus;
       
    50 }
       
    51 
       
    52 /* Create a new slave device.  */
       
    53 i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
       
    54 {
       
    55     i2c_slave *dev;
       
    56 
       
    57     if (size < sizeof(i2c_slave))
       
    58         hw_error("I2C struct too small");
       
    59 
       
    60     dev = (i2c_slave *)qemu_mallocz(size);
       
    61     dev->address = address;
       
    62     dev->next = bus->dev;
       
    63     bus->dev = dev;
       
    64     dev->bus = bus;
       
    65 
       
    66     return dev;
       
    67 }
       
    68 
       
    69 void i2c_set_slave_address(i2c_slave *dev, int address)
       
    70 {
       
    71     dev->address = address;
       
    72 }
       
    73 
       
    74 /* Return nonzero if bus is busy.  */
       
    75 int i2c_bus_busy(i2c_bus *bus)
       
    76 {
       
    77     return bus->current_dev != NULL;
       
    78 }
       
    79 
       
    80 /* Returns non-zero if the address is not valid.  */
       
    81 /* TODO: Make this handle multiple masters.  */
       
    82 int i2c_start_transfer(i2c_bus *bus, int address, int recv)
       
    83 {
       
    84     i2c_slave *dev;
       
    85 
       
    86     for (dev = bus->dev; dev; dev = dev->next) {
       
    87         if (dev->address == address)
       
    88             break;
       
    89     }
       
    90 
       
    91     if (!dev)
       
    92         return 1;
       
    93 
       
    94     /* If the bus is already busy, assume this is a repeated
       
    95        start condition.  */
       
    96     bus->current_dev = dev;
       
    97     dev->event(dev, recv ? I2C_START_RECV : I2C_START_SEND);
       
    98     return 0;
       
    99 }
       
   100 
       
   101 void i2c_end_transfer(i2c_bus *bus)
       
   102 {
       
   103     i2c_slave *dev = bus->current_dev;
       
   104 
       
   105     if (!dev)
       
   106         return;
       
   107 
       
   108     dev->event(dev, I2C_FINISH);
       
   109 
       
   110     bus->current_dev = NULL;
       
   111 }
       
   112 
       
   113 int i2c_send(i2c_bus *bus, uint8_t data)
       
   114 {
       
   115     i2c_slave *dev = bus->current_dev;
       
   116 
       
   117     if (!dev)
       
   118         return -1;
       
   119 
       
   120     return dev->send(dev, data);
       
   121 }
       
   122 
       
   123 int i2c_recv(i2c_bus *bus)
       
   124 {
       
   125     i2c_slave *dev = bus->current_dev;
       
   126 
       
   127     if (!dev)
       
   128         return -1;
       
   129 
       
   130     return dev->recv(dev);
       
   131 }
       
   132 
       
   133 void i2c_nack(i2c_bus *bus)
       
   134 {
       
   135     i2c_slave *dev = bus->current_dev;
       
   136 
       
   137     if (!dev)
       
   138         return;
       
   139 
       
   140     dev->event(dev, I2C_NACK);
       
   141 }
       
   142 
       
   143 void i2c_slave_save(QEMUFile *f, i2c_slave *dev)
       
   144 {
       
   145     qemu_put_byte(f, dev->address);
       
   146 }
       
   147 
       
   148 void i2c_slave_load(QEMUFile *f, i2c_slave *dev)
       
   149 {
       
   150     dev->address = qemu_get_byte(f);
       
   151     if (dev->bus->saved_address == dev->address)
       
   152         dev->bus->current_dev = dev;
       
   153 }