cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

smbus_master.c (3437B)


      1/*
      2 * QEMU SMBus host (master) emulation.
      3 *
      4 * This code emulates SMBus transactions from the master point of view,
      5 * it runs the individual I2C transaction to do the SMBus protocol
      6 * over I2C.
      7 *
      8 * Copyright (c) 2007 CodeSourcery.
      9 * Written by Paul Brook
     10 *
     11 * This code is licensed under the LGPL.
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "hw/i2c/i2c.h"
     16#include "hw/i2c/smbus_master.h"
     17
     18/* Master device commands.  */
     19int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
     20{
     21    if (i2c_start_transfer(bus, addr, read)) {
     22        return -1;
     23    }
     24    i2c_end_transfer(bus);
     25    return 0;
     26}
     27
     28int smbus_receive_byte(I2CBus *bus, uint8_t addr)
     29{
     30    uint8_t data;
     31
     32    if (i2c_start_recv(bus, addr)) {
     33        return -1;
     34    }
     35    data = i2c_recv(bus);
     36    i2c_nack(bus);
     37    i2c_end_transfer(bus);
     38    return data;
     39}
     40
     41int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
     42{
     43    if (i2c_start_send(bus, addr)) {
     44        return -1;
     45    }
     46    i2c_send(bus, data);
     47    i2c_end_transfer(bus);
     48    return 0;
     49}
     50
     51int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
     52{
     53    uint8_t data;
     54    if (i2c_start_send(bus, addr)) {
     55        return -1;
     56    }
     57    i2c_send(bus, command);
     58    if (i2c_start_recv(bus, addr)) {
     59        i2c_end_transfer(bus);
     60        return -1;
     61    }
     62    data = i2c_recv(bus);
     63    i2c_nack(bus);
     64    i2c_end_transfer(bus);
     65    return data;
     66}
     67
     68int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
     69{
     70    if (i2c_start_send(bus, addr)) {
     71        return -1;
     72    }
     73    i2c_send(bus, command);
     74    i2c_send(bus, data);
     75    i2c_end_transfer(bus);
     76    return 0;
     77}
     78
     79int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
     80{
     81    uint16_t data;
     82    if (i2c_start_send(bus, addr)) {
     83        return -1;
     84    }
     85    i2c_send(bus, command);
     86    if (i2c_start_recv(bus, addr)) {
     87        i2c_end_transfer(bus);
     88        return -1;
     89    }
     90    data = i2c_recv(bus);
     91    data |= i2c_recv(bus) << 8;
     92    i2c_nack(bus);
     93    i2c_end_transfer(bus);
     94    return data;
     95}
     96
     97int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
     98{
     99    if (i2c_start_send(bus, addr)) {
    100        return -1;
    101    }
    102    i2c_send(bus, command);
    103    i2c_send(bus, data & 0xff);
    104    i2c_send(bus, data >> 8);
    105    i2c_end_transfer(bus);
    106    return 0;
    107}
    108
    109int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
    110                     int len, bool recv_len, bool send_cmd)
    111{
    112    int rlen;
    113    int i;
    114
    115    if (send_cmd) {
    116        if (i2c_start_send(bus, addr)) {
    117            return -1;
    118        }
    119        i2c_send(bus, command);
    120    }
    121    if (i2c_start_recv(bus, addr)) {
    122        if (send_cmd) {
    123            i2c_end_transfer(bus);
    124        }
    125        return -1;
    126    }
    127    if (recv_len) {
    128        rlen = i2c_recv(bus);
    129    } else {
    130        rlen = len;
    131    }
    132    if (rlen > len) {
    133        rlen = 0;
    134    }
    135    for (i = 0; i < rlen; i++) {
    136        data[i] = i2c_recv(bus);
    137    }
    138    i2c_nack(bus);
    139    i2c_end_transfer(bus);
    140    return rlen;
    141}
    142
    143int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
    144                      int len, bool send_len)
    145{
    146    int i;
    147
    148    if (len > 32) {
    149        len = 32;
    150    }
    151
    152    if (i2c_start_send(bus, addr)) {
    153        return -1;
    154    }
    155    i2c_send(bus, command);
    156    if (send_len) {
    157        i2c_send(bus, len);
    158    }
    159    for (i = 0; i < len; i++) {
    160        i2c_send(bus, data[i]);
    161    }
    162    i2c_end_transfer(bus);
    163    return 0;
    164}